xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision a2caa4929e8e8a2ffff4ee5f03ab37a9be7462a0)
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 // It's legal for the assignment operator to take its source parameter by value.
2217 // Check that we handle this correctly. (This is a repro -- we used to
2218 // assert-fail on this.)
2219 TEST(TransferTest, AssignmentOperator_ArgByValue) {
2220   std::string Code = R"(
2221     struct A {
2222       int Baz;
2223       A &operator=(A);
2224     };
2225 
2226     void target() {
2227       A Foo = { 1 };
2228       A Bar = { 2 };
2229       Foo = Bar;
2230       // [[p]]
2231     }
2232   )";
2233   runDataflow(
2234       Code,
2235       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2236          ASTContext &ASTCtx) {
2237         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2238         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2239 
2240         const auto &FooLoc =
2241             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2242         const auto &BarLoc =
2243             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2244 
2245         const auto *FooBazVal =
2246             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2247         const auto *BarBazVal =
2248             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2249         EXPECT_EQ(FooBazVal, BarBazVal);
2250       });
2251 }
2252 
2253 TEST(TransferTest, AssignmentOperatorFromBase) {
2254   // This is a crash repro. We don't model the copy this case, so no
2255   // expectations on the copied field of the base class are checked.
2256   std::string Code = R"(
2257     struct Base {
2258       int base;
2259     };
2260     struct Derived : public Base {
2261       using Base::operator=;
2262       int derived;
2263     };
2264     void target(Base B, Derived D) {
2265       D.base = 1;
2266       D.derived = 1;
2267       D = B;
2268       // [[p]]
2269     }
2270   )";
2271   runDataflow(
2272       Code,
2273       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2274          ASTContext &ASTCtx) {});
2275 }
2276 
2277 TEST(TransferTest, AssignmentOperatorFromCallResult) {
2278   std::string Code = R"(
2279     struct A {};
2280     A ReturnA();
2281 
2282     void target() {
2283       A MyA;
2284       MyA = ReturnA();
2285     }
2286   )";
2287   runDataflow(
2288       Code,
2289       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2290          ASTContext &ASTCtx) {
2291         // As of this writing, we don't produce a `Value` for the call
2292         // `ReturnA()`. The only condition we're testing for is that the
2293         // analysis should not crash in this case.
2294       });
2295 }
2296 
2297 TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) {
2298   // This is a crash repro.
2299   std::string Code = R"(
2300     struct B { int Foo; };
2301     struct S : public B {};
2302     void target() {
2303       S S1 = { 1 };
2304       S S2;
2305       S S3;
2306       S1 = S2;  // Only Dst has InitListExpr.
2307       S3 = S1;  // Only Src has InitListExpr.
2308       // [[p]]
2309     }
2310   )";
2311   runDataflow(
2312       Code,
2313       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2314          ASTContext &ASTCtx) {});
2315 }
2316 
2317 TEST(TransferTest, CopyConstructor) {
2318   std::string Code = R"(
2319     struct A {
2320       int Baz;
2321     };
2322 
2323     void target() {
2324       A Foo = { 1 };
2325       A Bar = Foo;
2326       // [[after_copy]]
2327       Foo.Baz = 2;
2328       // [[after_update]]
2329     }
2330   )";
2331   runDataflow(
2332       Code,
2333       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2334          ASTContext &ASTCtx) {
2335         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2336         ASSERT_THAT(FooDecl, NotNull());
2337 
2338         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2339         ASSERT_THAT(BarDecl, NotNull());
2340 
2341         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2342         ASSERT_THAT(BazDecl, NotNull());
2343 
2344         // after_copy
2345         {
2346           const Environment &Env =
2347               getEnvironmentAtAnnotation(Results, "after_copy");
2348 
2349           const auto *FooLoc =
2350               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2351           const auto *BarLoc =
2352               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2353 
2354           // `Foo` and `Bar` have different `RecordValue`s associated with them.
2355           const auto *FooVal = cast<RecordValue>(Env.getValue(*FooLoc));
2356           const auto *BarVal = cast<RecordValue>(Env.getValue(*BarLoc));
2357           EXPECT_NE(FooVal, BarVal);
2358 
2359           // But the records compare equal.
2360           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2361 
2362           // In particular, the value of `Baz` in both records is the same.
2363           const auto *FooBazVal =
2364               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2365           const auto *BarBazVal =
2366               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2367           EXPECT_EQ(FooBazVal, BarBazVal);
2368         }
2369 
2370         // after_update
2371         {
2372           const Environment &Env =
2373               getEnvironmentAtAnnotation(Results, "after_update");
2374 
2375           const auto *FooLoc =
2376               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2377           const auto *BarLoc =
2378               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2379 
2380           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2381 
2382           const auto *FooBazVal =
2383               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2384           const auto *BarBazVal =
2385               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2386           EXPECT_NE(FooBazVal, BarBazVal);
2387         }
2388       });
2389 }
2390 
2391 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2392   std::string Code = R"(
2393     struct A {
2394       int Baz;
2395       A() = default;
2396       A(const A& a, bool def = true) { Baz = a.Baz; }
2397     };
2398 
2399     void target() {
2400       A Foo;
2401       (void)Foo.Baz;
2402       A Bar = Foo;
2403       // [[p]]
2404     }
2405   )";
2406   runDataflow(
2407       Code,
2408       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2409          ASTContext &ASTCtx) {
2410         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2411         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2412 
2413         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2414         ASSERT_THAT(FooDecl, NotNull());
2415 
2416         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2417         ASSERT_THAT(BarDecl, NotNull());
2418 
2419         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2420         ASSERT_THAT(BazDecl, NotNull());
2421 
2422         const auto *FooLoc =
2423             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2424         const auto *BarLoc =
2425             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2426         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2427 
2428         const auto *FooBazVal =
2429             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2430         const auto *BarBazVal =
2431             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2432         EXPECT_EQ(FooBazVal, BarBazVal);
2433       });
2434 }
2435 
2436 TEST(TransferTest, CopyConstructorWithParens) {
2437   std::string Code = R"(
2438     struct A {
2439       int Baz;
2440     };
2441 
2442     void target() {
2443       A Foo;
2444       (void)Foo.Baz;
2445       A Bar((A(Foo)));
2446       // [[p]]
2447     }
2448   )";
2449   runDataflow(
2450       Code,
2451       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2452          ASTContext &ASTCtx) {
2453         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2454         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2455 
2456         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2457         ASSERT_THAT(FooDecl, NotNull());
2458 
2459         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2460         ASSERT_THAT(BarDecl, NotNull());
2461 
2462         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2463         ASSERT_THAT(BazDecl, NotNull());
2464 
2465         const auto *FooLoc =
2466             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2467         const auto *BarLoc =
2468             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2469         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2470 
2471         const auto *FooBazVal =
2472             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2473         const auto *BarBazVal =
2474             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2475         EXPECT_EQ(FooBazVal, BarBazVal);
2476       });
2477 }
2478 
2479 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {
2480   std::string Code = R"(
2481   struct A {
2482     int Baz;
2483   };
2484   void target() {
2485     A Foo = {3};
2486     (void)Foo.Baz;
2487     A Bar = {A(Foo)};
2488     // [[p]]
2489   }
2490   )";
2491   runDataflow(
2492       Code,
2493       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2494          ASTContext &ASTCtx) {
2495         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2496 
2497         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2498 
2499         const auto &FooLoc =
2500             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2501         const auto &BarLoc =
2502             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2503 
2504         const auto *FooBazVal =
2505             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2506         const auto *BarBazVal =
2507             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2508         EXPECT_EQ(FooBazVal, BarBazVal);
2509       });
2510 }
2511 
2512 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2513   // This is a crash repro.
2514   std::string Code = R"(
2515     struct S {};
2516     const S &returnsSRef();
2517     void target() {
2518       S s(returnsSRef());
2519     }
2520   )";
2521   runDataflow(
2522       Code,
2523       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2524          ASTContext &ASTCtx) {});
2525 }
2526 
2527 TEST(TransferTest, MoveConstructor) {
2528   std::string Code = R"(
2529     namespace std {
2530 
2531     template <typename T> struct remove_reference      { using type = T; };
2532     template <typename T> struct remove_reference<T&>  { using type = T; };
2533     template <typename T> struct remove_reference<T&&> { using type = T; };
2534 
2535     template <typename T>
2536     using remove_reference_t = typename remove_reference<T>::type;
2537 
2538     template <typename T>
2539     std::remove_reference_t<T>&& move(T&& x);
2540 
2541     } // namespace std
2542 
2543     struct A {
2544       int Baz;
2545     };
2546 
2547     void target() {
2548       A Foo;
2549       A Bar;
2550       (void)Foo.Baz;
2551       // [[p1]]
2552       Foo = std::move(Bar);
2553       // [[p2]]
2554     }
2555   )";
2556   runDataflow(
2557       Code,
2558       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2559          ASTContext &ASTCtx) {
2560         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2561         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2562         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2563 
2564         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2565         ASSERT_THAT(FooDecl, NotNull());
2566 
2567         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2568         ASSERT_THAT(BarDecl, NotNull());
2569 
2570         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2571         ASSERT_THAT(BazDecl, NotNull());
2572 
2573         const auto *FooLoc1 =
2574             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2575         const auto *BarLoc1 =
2576             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2577 
2578         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2579 
2580         const auto *FooVal1 = cast<RecordValue>(Env1.getValue(*FooLoc1));
2581         const auto *BarVal1 = cast<RecordValue>(Env1.getValue(*BarLoc1));
2582         EXPECT_NE(FooVal1, BarVal1);
2583 
2584         const auto *FooBazVal1 =
2585             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2586         const auto *BarBazVal1 =
2587             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2588         EXPECT_NE(FooBazVal1, BarBazVal1);
2589 
2590         const auto *FooLoc2 =
2591             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2592         const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
2593         EXPECT_NE(FooVal2, BarVal1);
2594         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2595 
2596         const auto *FooBazVal2 =
2597             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2598         EXPECT_EQ(FooBazVal2, BarBazVal1);
2599       });
2600 }
2601 
2602 TEST(TransferTest, BindTemporary) {
2603   std::string Code = R"(
2604     struct A {
2605       virtual ~A() = default;
2606 
2607       int Baz;
2608     };
2609 
2610     void target(A Foo) {
2611       int Bar = A(Foo).Baz;
2612       // [[p]]
2613     }
2614   )";
2615   runDataflow(
2616       Code,
2617       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2618          ASTContext &ASTCtx) {
2619         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2620         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2621 
2622         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2623         ASSERT_THAT(FooDecl, NotNull());
2624 
2625         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2626         ASSERT_THAT(BarDecl, NotNull());
2627 
2628         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2629         ASSERT_THAT(BazDecl, NotNull());
2630 
2631         const auto &FooLoc =
2632             *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2633         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2634         EXPECT_EQ(BarVal, getFieldValue(&FooLoc, *BazDecl, Env));
2635       });
2636 }
2637 
2638 TEST(TransferTest, ResultObjectLocation) {
2639   std::string Code = R"(
2640     struct A {
2641       virtual ~A() = default;
2642     };
2643 
2644     void target() {
2645       0, A();
2646       (void)0; // [[p]]
2647     }
2648   )";
2649   using ast_matchers::binaryOperator;
2650   using ast_matchers::cxxBindTemporaryExpr;
2651   using ast_matchers::cxxTemporaryObjectExpr;
2652   using ast_matchers::exprWithCleanups;
2653   using ast_matchers::has;
2654   using ast_matchers::hasOperatorName;
2655   using ast_matchers::hasRHS;
2656   using ast_matchers::match;
2657   using ast_matchers::selectFirst;
2658   using ast_matchers::traverse;
2659   runDataflow(
2660       Code,
2661       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2662          ASTContext &ASTCtx) {
2663         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2664 
2665         // The expression `0, A()` in the code above produces the following
2666         // structure, consisting of four prvalues of record type.
2667         // `Env.getResultObjectLocation()` should return the same location for
2668         // all of these.
2669         auto MatchResult = match(
2670             traverse(TK_AsIs,
2671                      exprWithCleanups(
2672                          has(binaryOperator(
2673                                  hasOperatorName(","),
2674                                  hasRHS(cxxBindTemporaryExpr(
2675                                             has(cxxTemporaryObjectExpr().bind(
2676                                                 "toe")))
2677                                             .bind("bte")))
2678                                  .bind("comma")))
2679                          .bind("ewc")),
2680             ASTCtx);
2681         auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
2682         ASSERT_NE(TOE, nullptr);
2683         auto *Comma = selectFirst<BinaryOperator>("comma", MatchResult);
2684         ASSERT_NE(Comma, nullptr);
2685         auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
2686         ASSERT_NE(EWC, nullptr);
2687         auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
2688         ASSERT_NE(BTE, nullptr);
2689 
2690         RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
2691         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*Comma));
2692         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
2693         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
2694       });
2695 }
2696 
2697 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
2698   std::string Code = R"(
2699     struct S {};
2700     struct target {
2701       target () {
2702         (void)0;
2703         // [[p]]
2704       }
2705       S s = {};
2706     };
2707   )";
2708 
2709   using ast_matchers::cxxCtorInitializer;
2710   using ast_matchers::match;
2711   using ast_matchers::selectFirst;
2712   runDataflow(
2713       Code,
2714       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2715          ASTContext &ASTCtx) {
2716         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2717 
2718         const ValueDecl *SField = findValueDecl(ASTCtx, "s");
2719 
2720         auto *CtorInit = selectFirst<CXXCtorInitializer>(
2721             "ctor_initializer",
2722             match(cxxCtorInitializer().bind("ctor_initializer"), ASTCtx));
2723         ASSERT_NE(CtorInit, nullptr);
2724 
2725         auto *DefaultInit = cast<CXXDefaultInitExpr>(CtorInit->getInit());
2726 
2727         RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
2728 
2729         // FIXME: The result object location for the `CXXDefaultInitExpr` should
2730         // be the location of the member variable being initialized, but we
2731         // don't do this correctly yet; see also comments in
2732         // `builtinTransferInitializer()`.
2733         // For the time being, we just document the current erroneous behavior
2734         // here (this should be `EXPECT_EQ` when the behavior is fixed).
2735         EXPECT_NE(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
2736       });
2737 }
2738 
2739 TEST(TransferTest, StaticCast) {
2740   std::string Code = R"(
2741     void target(int Foo) {
2742       int Bar = static_cast<int>(Foo);
2743       // [[p]]
2744     }
2745   )";
2746   runDataflow(
2747       Code,
2748       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2749          ASTContext &ASTCtx) {
2750         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2751         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2752 
2753         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2754         ASSERT_THAT(FooDecl, NotNull());
2755 
2756         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2757         ASSERT_THAT(BarDecl, NotNull());
2758 
2759         const auto *FooVal = Env.getValue(*FooDecl);
2760         const auto *BarVal = Env.getValue(*BarDecl);
2761         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2762         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2763         EXPECT_EQ(FooVal, BarVal);
2764       });
2765 }
2766 
2767 TEST(TransferTest, IntegralCast) {
2768   std::string Code = R"(
2769     void target(int Foo) {
2770       long Bar = Foo;
2771       // [[p]]
2772     }
2773   )";
2774   runDataflow(
2775       Code,
2776       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2777          ASTContext &ASTCtx) {
2778         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2779         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2780 
2781         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2782         ASSERT_THAT(FooDecl, NotNull());
2783 
2784         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2785         ASSERT_THAT(BarDecl, NotNull());
2786 
2787         const auto *FooVal = Env.getValue(*FooDecl);
2788         const auto *BarVal = Env.getValue(*BarDecl);
2789         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2790         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2791         EXPECT_EQ(FooVal, BarVal);
2792       });
2793 }
2794 
2795 TEST(TransferTest, IntegraltoBooleanCast) {
2796   std::string Code = R"(
2797     void target(int Foo) {
2798       bool Bar = Foo;
2799       // [[p]]
2800     }
2801   )";
2802   runDataflow(
2803       Code,
2804       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2805          ASTContext &ASTCtx) {
2806         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2807         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2808 
2809         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2810         ASSERT_THAT(FooDecl, NotNull());
2811 
2812         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2813         ASSERT_THAT(BarDecl, NotNull());
2814 
2815         const auto *FooVal = Env.getValue(*FooDecl);
2816         const auto *BarVal = Env.getValue(*BarDecl);
2817         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2818         EXPECT_TRUE(isa<BoolValue>(BarVal));
2819       });
2820 }
2821 
2822 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2823   std::string Code = R"(
2824     void target(bool Foo) {
2825       int Zab = Foo;
2826       bool Bar = Zab;
2827       // [[p]]
2828     }
2829   )";
2830   runDataflow(
2831       Code,
2832       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2833          ASTContext &ASTCtx) {
2834         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2835         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2836 
2837         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2838         ASSERT_THAT(FooDecl, NotNull());
2839 
2840         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2841         ASSERT_THAT(BarDecl, NotNull());
2842 
2843         const auto *FooVal = Env.getValue(*FooDecl);
2844         const auto *BarVal = Env.getValue(*BarDecl);
2845         EXPECT_TRUE(isa<BoolValue>(FooVal));
2846         EXPECT_TRUE(isa<BoolValue>(BarVal));
2847         EXPECT_EQ(FooVal, BarVal);
2848       });
2849 }
2850 
2851 TEST(TransferTest, NullToPointerCast) {
2852   std::string Code = R"(
2853     using my_nullptr_t = decltype(nullptr);
2854     struct Baz {};
2855     void target() {
2856       int *FooX = nullptr;
2857       int *FooY = nullptr;
2858       bool **Bar = nullptr;
2859       Baz *Baz = nullptr;
2860       my_nullptr_t Null = 0;
2861       // [[p]]
2862     }
2863   )";
2864   runDataflow(
2865       Code,
2866       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2867          ASTContext &ASTCtx) {
2868         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2869         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2870 
2871         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2872         ASSERT_THAT(FooXDecl, NotNull());
2873 
2874         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2875         ASSERT_THAT(FooYDecl, NotNull());
2876 
2877         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2878         ASSERT_THAT(BarDecl, NotNull());
2879 
2880         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2881         ASSERT_THAT(BazDecl, NotNull());
2882 
2883         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2884         ASSERT_THAT(NullDecl, NotNull());
2885 
2886         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
2887         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
2888         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2889         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
2890         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
2891 
2892         EXPECT_EQ(FooXVal, FooYVal);
2893         EXPECT_NE(FooXVal, BarVal);
2894         EXPECT_NE(FooXVal, BazVal);
2895         EXPECT_NE(BarVal, BazVal);
2896 
2897         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2898         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2899         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2900 
2901         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2902         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2903         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2904 
2905         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2906         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
2907         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2908 
2909         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
2910         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2911         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2912       });
2913 }
2914 
2915 TEST(TransferTest, PointerToMemberVariable) {
2916   std::string Code = R"(
2917     struct S {
2918       int i;
2919     };
2920     void target() {
2921       int S::*MemberPointer = &S::i;
2922       // [[p]]
2923     }
2924   )";
2925   runDataflow(
2926       Code,
2927       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2928          ASTContext &ASTCtx) {
2929         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2930 
2931         const ValueDecl *MemberPointerDecl =
2932             findValueDecl(ASTCtx, "MemberPointer");
2933         ASSERT_THAT(MemberPointerDecl, NotNull());
2934         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2935       });
2936 }
2937 
2938 TEST(TransferTest, PointerToMemberFunction) {
2939   std::string Code = R"(
2940     struct S {
2941       void Method();
2942     };
2943     void target() {
2944       void (S::*MemberPointer)() = &S::Method;
2945       // [[p]]
2946     }
2947   )";
2948   runDataflow(
2949       Code,
2950       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2951          ASTContext &ASTCtx) {
2952         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2953 
2954         const ValueDecl *MemberPointerDecl =
2955             findValueDecl(ASTCtx, "MemberPointer");
2956         ASSERT_THAT(MemberPointerDecl, NotNull());
2957         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2958       });
2959 }
2960 
2961 TEST(TransferTest, NullToMemberPointerCast) {
2962   std::string Code = R"(
2963     struct Foo {};
2964     void target() {
2965       int Foo::*MemberPointer = nullptr;
2966       // [[p]]
2967     }
2968   )";
2969   runDataflow(
2970       Code,
2971       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2972          ASTContext &ASTCtx) {
2973         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2974         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2975 
2976         const ValueDecl *MemberPointerDecl =
2977             findValueDecl(ASTCtx, "MemberPointer");
2978         ASSERT_THAT(MemberPointerDecl, NotNull());
2979         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2980       });
2981 }
2982 
2983 TEST(TransferTest, AddrOfValue) {
2984   std::string Code = R"(
2985     void target() {
2986       int Foo;
2987       int *Bar = &Foo;
2988       // [[p]]
2989     }
2990   )";
2991   runDataflow(
2992       Code,
2993       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2994          ASTContext &ASTCtx) {
2995         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2996         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2997 
2998         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2999         ASSERT_THAT(FooDecl, NotNull());
3000 
3001         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3002         ASSERT_THAT(BarDecl, NotNull());
3003 
3004         const auto *FooLoc =
3005             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3006         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3007         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3008       });
3009 }
3010 
3011 TEST(TransferTest, AddrOfReference) {
3012   std::string Code = R"(
3013     void target(int *Foo) {
3014       int *Bar = &(*Foo);
3015       // [[p]]
3016     }
3017   )";
3018   runDataflow(
3019       Code,
3020       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3021          ASTContext &ASTCtx) {
3022         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3023         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3024 
3025         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3026         ASSERT_THAT(FooDecl, NotNull());
3027 
3028         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3029         ASSERT_THAT(BarDecl, NotNull());
3030 
3031         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3032         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3033         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3034       });
3035 }
3036 
3037 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3038   std::string Code = R"(
3039     template <typename T>
3040     void target() {}
3041   )";
3042   ASSERT_THAT_ERROR(
3043       checkDataflowWithNoopAnalysis(Code),
3044       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3045 }
3046 
3047 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3048   std::string Code = R"(
3049     template <typename T>
3050     struct A {
3051       void target() {}
3052     };
3053   )";
3054   ASSERT_THAT_ERROR(
3055       checkDataflowWithNoopAnalysis(Code),
3056       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3057 }
3058 
3059 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3060   std::string Code = R"(
3061     struct A {};
3062 
3063     void target(A Foo, A Bar, bool Cond) {
3064       A Baz = Cond ?  Foo : Bar;
3065       /*[[p]]*/
3066     }
3067   )";
3068   runDataflow(
3069       Code,
3070       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3071          ASTContext &ASTCtx) {
3072         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3073         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3074 
3075         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3076         ASSERT_THAT(FooDecl, NotNull());
3077 
3078         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3079         ASSERT_THAT(BarDecl, NotNull());
3080 
3081         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3082         ASSERT_THAT(BazDecl, NotNull());
3083 
3084         const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
3085         const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
3086 
3087         const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
3088         ASSERT_THAT(BazVal, NotNull());
3089 
3090         EXPECT_NE(BazVal, FooVal);
3091         EXPECT_NE(BazVal, BarVal);
3092       });
3093 }
3094 
3095 TEST(TransferTest, VarDeclInDoWhile) {
3096   std::string Code = R"(
3097     void target(int *Foo) {
3098       do {
3099         int Bar = *Foo;
3100         // [[in_loop]]
3101       } while (false);
3102       (void)0;
3103       // [[after_loop]]
3104     }
3105   )";
3106   runDataflow(
3107       Code,
3108       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3109          ASTContext &ASTCtx) {
3110         const Environment &EnvInLoop =
3111             getEnvironmentAtAnnotation(Results, "in_loop");
3112         const Environment &EnvAfterLoop =
3113             getEnvironmentAtAnnotation(Results, "after_loop");
3114 
3115         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3116         ASSERT_THAT(FooDecl, NotNull());
3117 
3118         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3119         ASSERT_THAT(BarDecl, NotNull());
3120 
3121         const auto *FooVal =
3122             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3123         const auto *FooPointeeVal =
3124             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3125 
3126         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3127         EXPECT_EQ(BarVal, FooPointeeVal);
3128 
3129         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3130       });
3131 }
3132 
3133 TEST(TransferTest, UnreachableAfterWhileTrue) {
3134   std::string Code = R"(
3135     void target() {
3136       while (true) {}
3137       (void)0;
3138       /*[[p]]*/
3139     }
3140   )";
3141   runDataflow(
3142       Code,
3143       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3144          ASTContext &ASTCtx) {
3145         // The node after the while-true is pruned because it is trivially
3146         // known to be unreachable.
3147         ASSERT_TRUE(Results.empty());
3148       });
3149 }
3150 
3151 TEST(TransferTest, AggregateInitialization) {
3152   std::string BracesCode = R"(
3153     struct A {
3154       int Foo;
3155     };
3156 
3157     struct B {
3158       int Bar;
3159       A Baz;
3160       int Qux;
3161     };
3162 
3163     void target(int BarArg, int FooArg, int QuxArg) {
3164       B Quux{BarArg, {FooArg}, QuxArg};
3165       B OtherB;
3166       /*[[p]]*/
3167     }
3168   )";
3169   std::string BraceElisionCode = R"(
3170     struct A {
3171       int Foo;
3172     };
3173 
3174     struct B {
3175       int Bar;
3176       A Baz;
3177       int Qux;
3178     };
3179 
3180     void target(int BarArg, int FooArg, int QuxArg) {
3181       B Quux = {BarArg, FooArg, QuxArg};
3182       B OtherB;
3183       /*[[p]]*/
3184     }
3185   )";
3186   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3187     runDataflow(
3188         Code,
3189         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3190            ASTContext &ASTCtx) {
3191           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3192           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3193 
3194           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3195           ASSERT_THAT(FooDecl, NotNull());
3196 
3197           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3198           ASSERT_THAT(BarDecl, NotNull());
3199 
3200           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3201           ASSERT_THAT(BazDecl, NotNull());
3202 
3203           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3204           ASSERT_THAT(QuxDecl, NotNull());
3205 
3206           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3207           ASSERT_THAT(FooArgDecl, NotNull());
3208 
3209           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3210           ASSERT_THAT(BarArgDecl, NotNull());
3211 
3212           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3213           ASSERT_THAT(QuxArgDecl, NotNull());
3214 
3215           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3216           ASSERT_THAT(QuuxDecl, NotNull());
3217 
3218           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3219           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3220           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3221 
3222           const auto &QuuxLoc =
3223               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3224           const auto &BazLoc =
3225               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3226 
3227           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3228           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3229           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3230 
3231           // Check that fields initialized in an initializer list are always
3232           // modeled in other instances of the same type.
3233           const auto &OtherBLoc =
3234               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3235           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3236           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3237           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3238         });
3239   }
3240 }
3241 
3242 TEST(TransferTest, AggregateInitializationReferenceField) {
3243   std::string Code = R"(
3244     struct S {
3245       int &RefField;
3246     };
3247 
3248     void target(int i) {
3249       S s = { i };
3250       /*[[p]]*/
3251     }
3252   )";
3253   runDataflow(
3254       Code,
3255       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3256          ASTContext &ASTCtx) {
3257         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3258 
3259         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3260 
3261         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3262         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3263 
3264         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3265       });
3266 }
3267 
3268 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3269   std::string Code = R"(
3270     struct S {
3271       int i1;
3272       int i2;
3273     };
3274 
3275     void target(int i) {
3276       S s = { i };
3277       /*[[p]]*/
3278     }
3279   )";
3280   runDataflow(
3281       Code,
3282       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3283          ASTContext &ASTCtx) {
3284         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3285 
3286         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3287         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3288 
3289         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3290 
3291         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3292         auto &I1Value =
3293             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3294         EXPECT_EQ(&I1Value, &IValue);
3295         auto &I2Value =
3296             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3297         EXPECT_NE(&I2Value, &IValue);
3298       });
3299 }
3300 
3301 TEST(TransferTest, AggregateInitializationFunctionPointer) {
3302   // This is a repro for an assertion failure.
3303   // nullptr takes on the type of a const function pointer, but its type was
3304   // asserted to be equal to the *unqualified* type of Field, which no longer
3305   // included the const.
3306   std::string Code = R"(
3307     struct S {
3308       void (*const Field)();
3309     };
3310 
3311     void target() {
3312       S s{nullptr};
3313     }
3314   )";
3315   runDataflow(
3316       Code,
3317       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3318          ASTContext &ASTCtx) {});
3319 }
3320 
3321 TEST(TransferTest, AssignToUnionMember) {
3322   std::string Code = R"(
3323     union A {
3324       int Foo;
3325     };
3326 
3327     void target(int Bar) {
3328       A Baz;
3329       Baz.Foo = Bar;
3330       // [[p]]
3331     }
3332   )";
3333   runDataflow(
3334       Code,
3335       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3336          ASTContext &ASTCtx) {
3337         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3338         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3339 
3340         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3341         ASSERT_THAT(BazDecl, NotNull());
3342         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3343 
3344         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3345         FieldDecl *FooDecl = nullptr;
3346         for (FieldDecl *Field : BazFields) {
3347           if (Field->getNameAsString() == "Foo") {
3348             FooDecl = Field;
3349           } else {
3350             FAIL() << "Unexpected field: " << Field->getNameAsString();
3351           }
3352         }
3353         ASSERT_THAT(FooDecl, NotNull());
3354 
3355         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
3356             Env.getStorageLocation(*BazDecl));
3357         ASSERT_THAT(BazLoc, NotNull());
3358         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
3359 
3360         const auto *FooVal =
3361             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
3362 
3363         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3364         ASSERT_THAT(BarDecl, NotNull());
3365         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
3366         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3367 
3368         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
3369       });
3370 }
3371 
3372 TEST(TransferTest, AssignFromBoolLiteral) {
3373   std::string Code = R"(
3374     void target() {
3375       bool Foo = true;
3376       bool Bar = false;
3377       // [[p]]
3378     }
3379   )";
3380   runDataflow(
3381       Code,
3382       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3383          ASTContext &ASTCtx) {
3384         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3385         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3386 
3387         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3388         ASSERT_THAT(FooDecl, NotNull());
3389 
3390         const auto *FooVal =
3391             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3392         ASSERT_THAT(FooVal, NotNull());
3393 
3394         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3395         ASSERT_THAT(BarDecl, NotNull());
3396 
3397         const auto *BarVal =
3398             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3399         ASSERT_THAT(BarVal, NotNull());
3400 
3401         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3402         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3403       });
3404 }
3405 
3406 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3407   {
3408     std::string Code = R"(
3409     void target(bool Foo, bool Bar, bool Qux) {
3410       bool Baz = (Foo) && (Bar || Qux);
3411       // [[p]]
3412     }
3413   )";
3414     runDataflow(
3415         Code,
3416         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3417            ASTContext &ASTCtx) {
3418           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3419           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3420 
3421           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3422           ASSERT_THAT(FooDecl, NotNull());
3423 
3424           const auto *FooVal =
3425               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3426           ASSERT_THAT(FooVal, NotNull());
3427 
3428           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3429           ASSERT_THAT(BarDecl, NotNull());
3430 
3431           const auto *BarVal =
3432               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3433           ASSERT_THAT(BarVal, NotNull());
3434 
3435           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3436           ASSERT_THAT(QuxDecl, NotNull());
3437 
3438           const auto *QuxVal =
3439               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3440           ASSERT_THAT(QuxVal, NotNull());
3441 
3442           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3443           ASSERT_THAT(BazDecl, NotNull());
3444 
3445           const auto *BazVal =
3446               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3447           ASSERT_THAT(BazVal, NotNull());
3448           auto &A = Env.arena();
3449           EXPECT_EQ(&BazVal->formula(),
3450                     &A.makeAnd(FooVal->formula(),
3451                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3452         });
3453   }
3454 
3455   {
3456     std::string Code = R"(
3457     void target(bool Foo, bool Bar, bool Qux) {
3458       bool Baz = (Foo && Qux) || (Bar);
3459       // [[p]]
3460     }
3461   )";
3462     runDataflow(
3463         Code,
3464         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3465            ASTContext &ASTCtx) {
3466           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3467           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3468 
3469           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3470           ASSERT_THAT(FooDecl, NotNull());
3471 
3472           const auto *FooVal =
3473               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3474           ASSERT_THAT(FooVal, NotNull());
3475 
3476           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3477           ASSERT_THAT(BarDecl, NotNull());
3478 
3479           const auto *BarVal =
3480               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3481           ASSERT_THAT(BarVal, NotNull());
3482 
3483           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3484           ASSERT_THAT(QuxDecl, NotNull());
3485 
3486           const auto *QuxVal =
3487               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3488           ASSERT_THAT(QuxVal, NotNull());
3489 
3490           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3491           ASSERT_THAT(BazDecl, NotNull());
3492 
3493           const auto *BazVal =
3494               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3495           ASSERT_THAT(BazVal, NotNull());
3496           auto &A = Env.arena();
3497           EXPECT_EQ(&BazVal->formula(),
3498                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3499                               BarVal->formula()));
3500         });
3501   }
3502 
3503   {
3504     std::string Code = R"(
3505       void target(bool A, bool B, bool C, bool D) {
3506         bool Foo = ((A && B) && C) && D;
3507         // [[p]]
3508       }
3509     )";
3510     runDataflow(
3511         Code,
3512         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3513            ASTContext &ASTCtx) {
3514           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3515           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3516 
3517           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
3518           ASSERT_THAT(ADecl, NotNull());
3519 
3520           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
3521           ASSERT_THAT(AVal, NotNull());
3522 
3523           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3524           ASSERT_THAT(BDecl, NotNull());
3525 
3526           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
3527           ASSERT_THAT(BVal, NotNull());
3528 
3529           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3530           ASSERT_THAT(CDecl, NotNull());
3531 
3532           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3533           ASSERT_THAT(CVal, NotNull());
3534 
3535           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3536           ASSERT_THAT(DDecl, NotNull());
3537 
3538           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3539           ASSERT_THAT(DVal, NotNull());
3540 
3541           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3542           ASSERT_THAT(FooDecl, NotNull());
3543 
3544           const auto *FooVal =
3545               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3546           ASSERT_THAT(FooVal, NotNull());
3547           auto &A = Env.arena();
3548           EXPECT_EQ(
3549               &FooVal->formula(),
3550               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
3551                                    CVal->formula()),
3552                          DVal->formula()));
3553         });
3554   }
3555 }
3556 
3557 TEST(TransferTest, AssignFromBoolNegation) {
3558   std::string Code = R"(
3559     void target() {
3560       bool Foo = true;
3561       bool Bar = !(Foo);
3562       // [[p]]
3563     }
3564   )";
3565   runDataflow(
3566       Code,
3567       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3568          ASTContext &ASTCtx) {
3569         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3570         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3571 
3572         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3573         ASSERT_THAT(FooDecl, NotNull());
3574 
3575         const auto *FooVal =
3576             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3577         ASSERT_THAT(FooVal, NotNull());
3578 
3579         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3580         ASSERT_THAT(BarDecl, NotNull());
3581 
3582         const auto *BarVal =
3583             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3584         ASSERT_THAT(BarVal, NotNull());
3585         auto &A = Env.arena();
3586         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
3587       });
3588 }
3589 
3590 TEST(TransferTest, BuiltinExpect) {
3591   std::string Code = R"(
3592     void target(long Foo) {
3593       long Bar = __builtin_expect(Foo, true);
3594       /*[[p]]*/
3595     }
3596   )";
3597   runDataflow(
3598       Code,
3599       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3600          ASTContext &ASTCtx) {
3601         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3602         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3603 
3604         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3605         ASSERT_THAT(FooDecl, NotNull());
3606 
3607         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3608         ASSERT_THAT(BarDecl, NotNull());
3609 
3610         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3611       });
3612 }
3613 
3614 // `__builtin_expect` takes and returns a `long` argument, so other types
3615 // involve casts. This verifies that we identify the input and output in that
3616 // case.
3617 TEST(TransferTest, BuiltinExpectBoolArg) {
3618   std::string Code = R"(
3619     void target(bool Foo) {
3620       bool Bar = __builtin_expect(Foo, true);
3621       /*[[p]]*/
3622     }
3623   )";
3624   runDataflow(
3625       Code,
3626       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3627          ASTContext &ASTCtx) {
3628         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3629         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3630 
3631         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3632         ASSERT_THAT(FooDecl, NotNull());
3633 
3634         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3635         ASSERT_THAT(BarDecl, NotNull());
3636 
3637         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3638       });
3639 }
3640 
3641 TEST(TransferTest, BuiltinUnreachable) {
3642   std::string Code = R"(
3643     void target(bool Foo) {
3644       bool Bar = false;
3645       if (Foo)
3646         Bar = Foo;
3647       else
3648         __builtin_unreachable();
3649       (void)0;
3650       /*[[p]]*/
3651     }
3652   )";
3653   runDataflow(
3654       Code,
3655       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3656          ASTContext &ASTCtx) {
3657         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3658         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3659 
3660         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3661         ASSERT_THAT(FooDecl, NotNull());
3662 
3663         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3664         ASSERT_THAT(BarDecl, NotNull());
3665 
3666         // `__builtin_unreachable` promises that the code is
3667         // unreachable, so the compiler treats the "then" branch as the
3668         // only possible predecessor of this statement.
3669         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3670       });
3671 }
3672 
3673 TEST(TransferTest, BuiltinTrap) {
3674   std::string Code = R"(
3675     void target(bool Foo) {
3676       bool Bar = false;
3677       if (Foo)
3678         Bar = Foo;
3679       else
3680         __builtin_trap();
3681       (void)0;
3682       /*[[p]]*/
3683     }
3684   )";
3685   runDataflow(
3686       Code,
3687       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3688          ASTContext &ASTCtx) {
3689         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3690         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3691 
3692         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3693         ASSERT_THAT(FooDecl, NotNull());
3694 
3695         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3696         ASSERT_THAT(BarDecl, NotNull());
3697 
3698         // `__builtin_trap` ensures program termination, so only the
3699         // "then" branch is a predecessor of this statement.
3700         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3701       });
3702 }
3703 
3704 TEST(TransferTest, BuiltinDebugTrap) {
3705   std::string Code = R"(
3706     void target(bool Foo) {
3707       bool Bar = false;
3708       if (Foo)
3709         Bar = Foo;
3710       else
3711         __builtin_debugtrap();
3712       (void)0;
3713       /*[[p]]*/
3714     }
3715   )";
3716   runDataflow(
3717       Code,
3718       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3719          ASTContext &ASTCtx) {
3720         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3721         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3722 
3723         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3724         ASSERT_THAT(FooDecl, NotNull());
3725 
3726         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3727         ASSERT_THAT(BarDecl, NotNull());
3728 
3729         // `__builtin_debugtrap` doesn't ensure program termination.
3730         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3731       });
3732 }
3733 
3734 TEST(TransferTest, StaticIntSingleVarDecl) {
3735   std::string Code = R"(
3736     void target() {
3737       static int Foo;
3738       // [[p]]
3739     }
3740   )";
3741   runDataflow(
3742       Code,
3743       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3744          ASTContext &ASTCtx) {
3745         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3746         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3747 
3748         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3749         ASSERT_THAT(FooDecl, NotNull());
3750 
3751         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3752         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3753 
3754         const Value *FooVal = Env.getValue(*FooLoc);
3755         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3756       });
3757 }
3758 
3759 TEST(TransferTest, StaticIntGroupVarDecl) {
3760   std::string Code = R"(
3761     void target() {
3762       static int Foo, Bar;
3763       (void)0;
3764       // [[p]]
3765     }
3766   )";
3767   runDataflow(
3768       Code,
3769       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3770          ASTContext &ASTCtx) {
3771         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3772         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3773 
3774         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3775         ASSERT_THAT(FooDecl, NotNull());
3776 
3777         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3778         ASSERT_THAT(BarDecl, NotNull());
3779 
3780         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3781         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3782 
3783         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3784         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3785 
3786         const Value *FooVal = Env.getValue(*FooLoc);
3787         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3788 
3789         const Value *BarVal = Env.getValue(*BarLoc);
3790         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3791 
3792         EXPECT_NE(FooVal, BarVal);
3793       });
3794 }
3795 
3796 TEST(TransferTest, GlobalIntVarDecl) {
3797   std::string Code = R"(
3798     static int Foo;
3799 
3800     void target() {
3801       int Bar = Foo;
3802       int Baz = Foo;
3803       // [[p]]
3804     }
3805   )";
3806   runDataflow(
3807       Code,
3808       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3809          ASTContext &ASTCtx) {
3810         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3811         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3812 
3813         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3814         ASSERT_THAT(BarDecl, NotNull());
3815 
3816         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3817         ASSERT_THAT(BazDecl, NotNull());
3818 
3819         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3820         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3821         EXPECT_EQ(BarVal, BazVal);
3822       });
3823 }
3824 
3825 TEST(TransferTest, StaticMemberIntVarDecl) {
3826   std::string Code = R"(
3827     struct A {
3828       static int Foo;
3829     };
3830 
3831     void target(A a) {
3832       int Bar = a.Foo;
3833       int Baz = a.Foo;
3834       // [[p]]
3835     }
3836   )";
3837   runDataflow(
3838       Code,
3839       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3840          ASTContext &ASTCtx) {
3841         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3842         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3843 
3844         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3845         ASSERT_THAT(BarDecl, NotNull());
3846 
3847         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3848         ASSERT_THAT(BazDecl, NotNull());
3849 
3850         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3851         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3852         EXPECT_EQ(BarVal, BazVal);
3853       });
3854 }
3855 
3856 TEST(TransferTest, StaticMemberRefVarDecl) {
3857   std::string Code = R"(
3858     struct A {
3859       static int &Foo;
3860     };
3861 
3862     void target(A a) {
3863       int Bar = a.Foo;
3864       int Baz = a.Foo;
3865       // [[p]]
3866     }
3867   )";
3868   runDataflow(
3869       Code,
3870       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3871          ASTContext &ASTCtx) {
3872         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3873         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3874 
3875         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3876         ASSERT_THAT(BarDecl, NotNull());
3877 
3878         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3879         ASSERT_THAT(BazDecl, NotNull());
3880 
3881         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3882         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3883         EXPECT_EQ(BarVal, BazVal);
3884       });
3885 }
3886 
3887 TEST(TransferTest, AssignMemberBeforeCopy) {
3888   std::string Code = R"(
3889     struct A {
3890       int Foo;
3891     };
3892 
3893     void target() {
3894       A A1;
3895       A A2;
3896       int Bar;
3897       A1.Foo = Bar;
3898       A2 = A1;
3899       // [[p]]
3900     }
3901   )";
3902   runDataflow(
3903       Code,
3904       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3905          ASTContext &ASTCtx) {
3906         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3907         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3908 
3909         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3910         ASSERT_THAT(FooDecl, NotNull());
3911 
3912         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3913         ASSERT_THAT(BarDecl, NotNull());
3914 
3915         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3916         ASSERT_THAT(A1Decl, NotNull());
3917 
3918         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3919         ASSERT_THAT(A2Decl, NotNull());
3920 
3921         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3922 
3923         const auto &A2Loc =
3924             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
3925         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
3926       });
3927 }
3928 
3929 TEST(TransferTest, BooleanEquality) {
3930   std::string Code = R"(
3931     void target(bool Bar) {
3932       bool Foo = true;
3933       if (Bar == Foo) {
3934         (void)0;
3935         /*[[p-then]]*/
3936       } else {
3937         (void)0;
3938         /*[[p-else]]*/
3939       }
3940     }
3941   )";
3942   runDataflow(
3943       Code,
3944       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3945          ASTContext &ASTCtx) {
3946         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3947         const Environment &EnvThen =
3948             getEnvironmentAtAnnotation(Results, "p-then");
3949         const Environment &EnvElse =
3950             getEnvironmentAtAnnotation(Results, "p-else");
3951 
3952         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3953         ASSERT_THAT(BarDecl, NotNull());
3954 
3955         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3956         EXPECT_TRUE(EnvThen.proves(BarValThen));
3957 
3958         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3959         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
3960       });
3961 }
3962 
3963 TEST(TransferTest, BooleanInequality) {
3964   std::string Code = R"(
3965     void target(bool Bar) {
3966       bool Foo = true;
3967       if (Bar != Foo) {
3968         (void)0;
3969         /*[[p-then]]*/
3970       } else {
3971         (void)0;
3972         /*[[p-else]]*/
3973       }
3974     }
3975   )";
3976   runDataflow(
3977       Code,
3978       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3979          ASTContext &ASTCtx) {
3980         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3981         const Environment &EnvThen =
3982             getEnvironmentAtAnnotation(Results, "p-then");
3983         const Environment &EnvElse =
3984             getEnvironmentAtAnnotation(Results, "p-else");
3985 
3986         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3987         ASSERT_THAT(BarDecl, NotNull());
3988 
3989         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3990         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
3991 
3992         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3993         EXPECT_TRUE(EnvElse.proves(BarValElse));
3994       });
3995 }
3996 
3997 TEST(TransferTest, IntegerLiteralEquality) {
3998   std::string Code = R"(
3999     void target() {
4000       bool equal = (42 == 42);
4001       // [[p]]
4002     }
4003   )";
4004   runDataflow(
4005       Code,
4006       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4007          ASTContext &ASTCtx) {
4008         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4009 
4010         auto &Equal =
4011             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4012         EXPECT_TRUE(Env.proves(Equal));
4013       });
4014 }
4015 
4016 TEST(TransferTest, CorrelatedBranches) {
4017   std::string Code = R"(
4018     void target(bool B, bool C) {
4019       if (B) {
4020         return;
4021       }
4022       (void)0;
4023       /*[[p0]]*/
4024       if (C) {
4025         B = true;
4026         /*[[p1]]*/
4027       }
4028       if (B) {
4029         (void)0;
4030         /*[[p2]]*/
4031       }
4032     }
4033   )";
4034   runDataflow(
4035       Code,
4036       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4037          ASTContext &ASTCtx) {
4038         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4039 
4040         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4041         ASSERT_THAT(CDecl, NotNull());
4042 
4043         {
4044           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4045           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4046           ASSERT_THAT(BDecl, NotNull());
4047           auto &BVal = getFormula(*BDecl, Env);
4048 
4049           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4050         }
4051 
4052         {
4053           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4054           auto &CVal = getFormula(*CDecl, Env);
4055           EXPECT_TRUE(Env.proves(CVal));
4056         }
4057 
4058         {
4059           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4060           auto &CVal = getFormula(*CDecl, Env);
4061           EXPECT_TRUE(Env.proves(CVal));
4062         }
4063       });
4064 }
4065 
4066 TEST(TransferTest, LoopWithAssignmentConverges) {
4067   std::string Code = R"(
4068     bool foo();
4069 
4070     void target() {
4071        do {
4072         bool Bar = foo();
4073         if (Bar) break;
4074         (void)Bar;
4075         /*[[p]]*/
4076       } while (true);
4077     }
4078   )";
4079   // The key property that we are verifying is implicit in `runDataflow` --
4080   // namely, that the analysis succeeds, rather than hitting the maximum number
4081   // of iterations.
4082   runDataflow(
4083       Code,
4084       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4085          ASTContext &ASTCtx) {
4086         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4087         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4088 
4089         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4090         ASSERT_THAT(BarDecl, NotNull());
4091 
4092         auto &BarVal = getFormula(*BarDecl, Env);
4093         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4094       });
4095 }
4096 
4097 TEST(TransferTest, LoopWithStagedAssignments) {
4098   std::string Code = R"(
4099     bool foo();
4100 
4101     void target() {
4102       bool Bar = false;
4103       bool Err = false;
4104       while (foo()) {
4105         if (Bar)
4106           Err = true;
4107         Bar = true;
4108         /*[[p]]*/
4109       }
4110     }
4111   )";
4112   runDataflow(
4113       Code,
4114       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4115          ASTContext &ASTCtx) {
4116         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4117         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4118 
4119         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4120         ASSERT_THAT(BarDecl, NotNull());
4121         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4122         ASSERT_THAT(ErrDecl, NotNull());
4123 
4124         auto &BarVal = getFormula(*BarDecl, Env);
4125         auto &ErrVal = getFormula(*ErrDecl, Env);
4126         EXPECT_TRUE(Env.proves(BarVal));
4127         // An unsound analysis, for example only evaluating the loop once, can
4128         // conclude that `Err` is false. So, we test that this conclusion is not
4129         // reached.
4130         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4131       });
4132 }
4133 
4134 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4135   std::string Code = R"(
4136     bool &foo();
4137 
4138     void target() {
4139        do {
4140         bool& Bar = foo();
4141         if (Bar) break;
4142         (void)Bar;
4143         /*[[p]]*/
4144       } while (true);
4145     }
4146   )";
4147   // The key property that we are verifying is that the analysis succeeds,
4148   // rather than hitting the maximum number of iterations.
4149   runDataflow(
4150       Code,
4151       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4152          ASTContext &ASTCtx) {
4153         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4154         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4155 
4156         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4157         ASSERT_THAT(BarDecl, NotNull());
4158 
4159         auto &BarVal = getFormula(*BarDecl, Env);
4160         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4161       });
4162 }
4163 
4164 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4165   std::string Code = R"(
4166     struct Lookup {
4167       int x;
4168     };
4169 
4170     void target(Lookup val, bool b) {
4171       const Lookup* l = nullptr;
4172       while (b) {
4173         l = &val;
4174         /*[[p-inner]]*/
4175       }
4176       (void)0;
4177       /*[[p-outer]]*/
4178     }
4179   )";
4180   // The key property that we are verifying is implicit in `runDataflow` --
4181   // namely, that the analysis succeeds, rather than hitting the maximum number
4182   // of iterations.
4183   runDataflow(
4184       Code,
4185       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4186          ASTContext &ASTCtx) {
4187         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4188         const Environment &InnerEnv =
4189             getEnvironmentAtAnnotation(Results, "p-inner");
4190         const Environment &OuterEnv =
4191             getEnvironmentAtAnnotation(Results, "p-outer");
4192 
4193         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4194         ASSERT_THAT(ValDecl, NotNull());
4195 
4196         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4197         ASSERT_THAT(LDecl, NotNull());
4198 
4199         // Inner.
4200         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4201         ASSERT_THAT(LVal, NotNull());
4202 
4203         EXPECT_EQ(&LVal->getPointeeLoc(),
4204                   InnerEnv.getStorageLocation(*ValDecl));
4205 
4206         // Outer.
4207         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4208         ASSERT_THAT(LVal, NotNull());
4209 
4210         // The loop body may not have been executed, so we should not conclude
4211         // that `l` points to `val`.
4212         EXPECT_NE(&LVal->getPointeeLoc(),
4213                   OuterEnv.getStorageLocation(*ValDecl));
4214       });
4215 }
4216 
4217 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4218   std::string Code = R"cc(
4219     bool some_condition();
4220 
4221     void target(int i1, int i2) {
4222       int *p = &i1;
4223       while (true) {
4224         (void)*p;
4225         if (some_condition())
4226           p = &i1;
4227         else
4228           p = &i2;
4229       }
4230     }
4231   )cc";
4232   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4233 }
4234 
4235 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4236   std::string Code = R"cc(
4237     struct Lookup {
4238       int x;
4239     };
4240 
4241     bool some_condition();
4242 
4243     void target(Lookup l1, Lookup l2) {
4244       Lookup *l = &l1;
4245       while (true) {
4246         (void)l->x;
4247         if (some_condition())
4248           l = &l1;
4249         else
4250           l = &l2;
4251       }
4252     }
4253   )cc";
4254   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4255 }
4256 
4257 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4258   std::string Code = R"cc(
4259     bool foo();
4260 
4261     void target() {
4262       bool c = false;
4263       while (foo() || foo()) {
4264         c = true;
4265       }
4266     }
4267   )cc";
4268   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4269 }
4270 
4271 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
4272   // Check that we can prove `b` is always false in the loop.
4273   // This test exercises the logic in `widenDistinctValues()` that preserves
4274   // information if the boolean can be proved to be either true or false in both
4275   // the previous and current iteration.
4276   std::string Code = R"cc(
4277     int return_int();
4278     void target() {
4279       bool b = return_int() == 0;
4280       if (b) return;
4281       while (true) {
4282         b;
4283         // [[p]]
4284         b = return_int() == 0;
4285         if (b) return;
4286       }
4287     }
4288   )cc";
4289   runDataflow(
4290       Code,
4291       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4292          ASTContext &ASTCtx) {
4293         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4294         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
4295         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
4296       });
4297 }
4298 
4299 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4300   std::string Code = R"(
4301     union Union {
4302       int A;
4303       float B;
4304     };
4305 
4306     void foo() {
4307       Union A;
4308       Union B;
4309       A = B;
4310     }
4311   )";
4312   // This is a crash regression test when calling the transfer function on a
4313   // `CXXThisExpr` that refers to a union.
4314   runDataflow(
4315       Code,
4316       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4317          ASTContext &) {},
4318       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4319 }
4320 
4321 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4322   std::string Code = R"(
4323     struct A {
4324       int Foo;
4325       int Bar;
4326     };
4327 
4328     void target() {
4329       int Qux;
4330       A Baz;
4331       Baz.Foo = Qux;
4332       auto &FooRef = Baz.Foo;
4333       auto &BarRef = Baz.Bar;
4334       auto &[BoundFooRef, BoundBarRef] = Baz;
4335       // [[p]]
4336     }
4337   )";
4338   runDataflow(
4339       Code,
4340       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4341          ASTContext &ASTCtx) {
4342         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4343         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4344 
4345         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4346         ASSERT_THAT(FooRefDecl, NotNull());
4347 
4348         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4349         ASSERT_THAT(BarRefDecl, NotNull());
4350 
4351         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4352         ASSERT_THAT(QuxDecl, NotNull());
4353 
4354         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4355         ASSERT_THAT(BoundFooRefDecl, NotNull());
4356 
4357         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4358         ASSERT_THAT(BoundBarRefDecl, NotNull());
4359 
4360         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4361         ASSERT_THAT(FooRefLoc, NotNull());
4362 
4363         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4364         ASSERT_THAT(BarRefLoc, NotNull());
4365 
4366         const Value *QuxVal = Env.getValue(*QuxDecl);
4367         ASSERT_THAT(QuxVal, NotNull());
4368 
4369         const StorageLocation *BoundFooRefLoc =
4370             Env.getStorageLocation(*BoundFooRefDecl);
4371         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4372 
4373         const StorageLocation *BoundBarRefLoc =
4374             Env.getStorageLocation(*BoundBarRefDecl);
4375         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4376 
4377         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4378       });
4379 }
4380 
4381 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4382   std::string Code = R"(
4383     struct A {
4384       int &Foo;
4385       int &Bar;
4386     };
4387 
4388     void target(A Baz) {
4389       int Qux;
4390       Baz.Foo = Qux;
4391       auto &FooRef = Baz.Foo;
4392       auto &BarRef = Baz.Bar;
4393       auto &[BoundFooRef, BoundBarRef] = Baz;
4394       // [[p]]
4395     }
4396   )";
4397   runDataflow(
4398       Code,
4399       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4400          ASTContext &ASTCtx) {
4401         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4402         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4403 
4404         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4405         ASSERT_THAT(FooRefDecl, NotNull());
4406 
4407         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4408         ASSERT_THAT(BarRefDecl, NotNull());
4409 
4410         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4411         ASSERT_THAT(QuxDecl, NotNull());
4412 
4413         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4414         ASSERT_THAT(BoundFooRefDecl, NotNull());
4415 
4416         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4417         ASSERT_THAT(BoundBarRefDecl, NotNull());
4418 
4419         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4420         ASSERT_THAT(FooRefLoc, NotNull());
4421 
4422         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4423         ASSERT_THAT(BarRefLoc, NotNull());
4424 
4425         const Value *QuxVal = Env.getValue(*QuxDecl);
4426         ASSERT_THAT(QuxVal, NotNull());
4427 
4428         const StorageLocation *BoundFooRefLoc =
4429             Env.getStorageLocation(*BoundFooRefDecl);
4430         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4431 
4432         const StorageLocation *BoundBarRefLoc =
4433             Env.getStorageLocation(*BoundBarRefDecl);
4434         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4435 
4436         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4437       });
4438 }
4439 
4440 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4441   std::string Code = R"(
4442     struct A {
4443       int Foo;
4444       int Bar;
4445     };
4446 
4447     void target() {
4448       int Qux;
4449       A Baz;
4450       Baz.Foo = Qux;
4451       auto &FooRef = Baz.Foo;
4452       auto &BarRef = Baz.Bar;
4453       auto [BoundFoo, BoundBar] = Baz;
4454       // [[p]]
4455     }
4456   )";
4457   runDataflow(
4458       Code,
4459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4460          ASTContext &ASTCtx) {
4461         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4462         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4463 
4464         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4465         ASSERT_THAT(FooRefDecl, NotNull());
4466 
4467         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4468         ASSERT_THAT(BarRefDecl, NotNull());
4469 
4470         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4471         ASSERT_THAT(BoundFooDecl, NotNull());
4472 
4473         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4474         ASSERT_THAT(BoundBarDecl, NotNull());
4475 
4476         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4477         ASSERT_THAT(QuxDecl, NotNull());
4478 
4479         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4480         ASSERT_THAT(FooRefLoc, NotNull());
4481 
4482         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4483         ASSERT_THAT(BarRefLoc, NotNull());
4484 
4485         const Value *QuxVal = Env.getValue(*QuxDecl);
4486         ASSERT_THAT(QuxVal, NotNull());
4487 
4488         const StorageLocation *BoundFooLoc =
4489             Env.getStorageLocation(*BoundFooDecl);
4490         EXPECT_NE(BoundFooLoc, FooRefLoc);
4491 
4492         const StorageLocation *BoundBarLoc =
4493             Env.getStorageLocation(*BoundBarDecl);
4494         EXPECT_NE(BoundBarLoc, BarRefLoc);
4495 
4496         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4497       });
4498 }
4499 
4500 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4501   std::string Code = R"(
4502     namespace std {
4503     using size_t = int;
4504     template <class> struct tuple_size;
4505     template <std::size_t, class> struct tuple_element;
4506     template <class...> class tuple;
4507 
4508     namespace {
4509     template <class T, T v>
4510     struct size_helper { static const T value = v; };
4511     } // namespace
4512 
4513     template <class... T>
4514     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4515 
4516     template <std::size_t I, class... T>
4517     struct tuple_element<I, tuple<T...>> {
4518       using type =  __type_pack_element<I, T...>;
4519     };
4520 
4521     template <class...> class tuple {};
4522 
4523     template <std::size_t I, class... T>
4524     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4525     } // namespace std
4526 
4527     std::tuple<bool, int> makeTuple();
4528 
4529     void target(bool B) {
4530       auto [BoundFoo, BoundBar] = makeTuple();
4531       bool Baz;
4532       // Include if-then-else to test interaction of `BindingDecl` with join.
4533       if (B) {
4534         Baz = BoundFoo;
4535         (void)BoundBar;
4536         // [[p1]]
4537       } else {
4538         Baz = BoundFoo;
4539       }
4540       (void)0;
4541       // [[p2]]
4542     }
4543   )";
4544   runDataflow(
4545       Code,
4546       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4547          ASTContext &ASTCtx) {
4548         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4549         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4550 
4551         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4552         ASSERT_THAT(BoundFooDecl, NotNull());
4553 
4554         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4555         ASSERT_THAT(BoundBarDecl, NotNull());
4556 
4557         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4558         ASSERT_THAT(BazDecl, NotNull());
4559 
4560         // BindingDecls always map to references -- either lvalue or rvalue, so
4561         // we still need to skip here.
4562         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4563         ASSERT_THAT(BoundFooValue, NotNull());
4564         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4565 
4566         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4567         ASSERT_THAT(BoundBarValue, NotNull());
4568         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4569 
4570         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4571         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4572 
4573         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4574 
4575         // Test that `BoundFooDecl` retains the value we expect, after the join.
4576         BoundFooValue = Env2.getValue(*BoundFooDecl);
4577         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4578       });
4579 }
4580 
4581 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4582   std::string Code = R"(
4583     namespace std {
4584     using size_t = int;
4585     template <class> struct tuple_size;
4586     template <std::size_t, class> struct tuple_element;
4587     template <class...> class tuple;
4588 
4589     namespace {
4590     template <class T, T v>
4591     struct size_helper { static const T value = v; };
4592     } // namespace
4593 
4594     template <class... T>
4595     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4596 
4597     template <std::size_t I, class... T>
4598     struct tuple_element<I, tuple<T...>> {
4599       using type =  __type_pack_element<I, T...>;
4600     };
4601 
4602     template <class...> class tuple {};
4603 
4604     template <std::size_t I, class... T>
4605     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4606     } // namespace std
4607 
4608     std::tuple<bool, int> &getTuple();
4609 
4610     void target(bool B) {
4611       auto &[BoundFoo, BoundBar] = getTuple();
4612       bool Baz;
4613       // Include if-then-else to test interaction of `BindingDecl` with join.
4614       if (B) {
4615         Baz = BoundFoo;
4616         (void)BoundBar;
4617         // [[p1]]
4618       } else {
4619         Baz = BoundFoo;
4620       }
4621       (void)0;
4622       // [[p2]]
4623     }
4624   )";
4625   runDataflow(
4626       Code,
4627       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4628          ASTContext &ASTCtx) {
4629         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4630         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4631 
4632         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4633         ASSERT_THAT(BoundFooDecl, NotNull());
4634 
4635         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4636         ASSERT_THAT(BoundBarDecl, NotNull());
4637 
4638         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4639         ASSERT_THAT(BazDecl, NotNull());
4640 
4641         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4642         ASSERT_THAT(BoundFooValue, NotNull());
4643         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4644 
4645         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4646         ASSERT_THAT(BoundBarValue, NotNull());
4647         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4648 
4649         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4650         // works as expected. We don't test aliasing properties of the
4651         // reference, because we don't model `std::get` and so have no way to
4652         // equate separate references into the tuple.
4653         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4654 
4655         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4656 
4657         // Test that `BoundFooDecl` retains the value we expect, after the join.
4658         BoundFooValue = Env2.getValue(*BoundFooDecl);
4659         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4660       });
4661 }
4662 
4663 TEST(TransferTest, BinaryOperatorComma) {
4664   std::string Code = R"(
4665     void target(int Foo, int Bar) {
4666       int &Baz = (Foo, Bar);
4667       // [[p]]
4668     }
4669   )";
4670   runDataflow(
4671       Code,
4672       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4673          ASTContext &ASTCtx) {
4674         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4675         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4676 
4677         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4678         ASSERT_THAT(BarDecl, NotNull());
4679 
4680         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4681         ASSERT_THAT(BazDecl, NotNull());
4682 
4683         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4684         ASSERT_THAT(BarLoc, NotNull());
4685 
4686         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4687         EXPECT_EQ(BazLoc, BarLoc);
4688       });
4689 }
4690 
4691 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4692   std::string Code = R"(
4693     void target(bool Foo) {
4694       if (Foo) {
4695         (void)0;
4696         // [[if_then]]
4697       } else {
4698         (void)0;
4699         // [[if_else]]
4700       }
4701     }
4702   )";
4703   runDataflow(
4704       Code,
4705       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4706          ASTContext &ASTCtx) {
4707         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4708         const Environment &ThenEnv =
4709             getEnvironmentAtAnnotation(Results, "if_then");
4710         const Environment &ElseEnv =
4711             getEnvironmentAtAnnotation(Results, "if_else");
4712 
4713         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4714         ASSERT_THAT(FooDecl, NotNull());
4715 
4716         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
4717         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
4718 
4719         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
4720         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
4721       });
4722 }
4723 
4724 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4725   std::string Code = R"(
4726     void target(bool Foo) {
4727       while (Foo) {
4728         (void)0;
4729         // [[loop_body]]
4730       }
4731       (void)0;
4732       // [[after_loop]]
4733     }
4734   )";
4735   runDataflow(
4736       Code,
4737       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4738          ASTContext &ASTCtx) {
4739         ASSERT_THAT(Results.keys(),
4740                     UnorderedElementsAre("loop_body", "after_loop"));
4741         const Environment &LoopBodyEnv =
4742             getEnvironmentAtAnnotation(Results, "loop_body");
4743         const Environment &AfterLoopEnv =
4744             getEnvironmentAtAnnotation(Results, "after_loop");
4745 
4746         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4747         ASSERT_THAT(FooDecl, NotNull());
4748 
4749         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
4750         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4751 
4752         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4753         EXPECT_TRUE(
4754             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4755       });
4756 }
4757 
4758 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4759   std::string Code = R"(
4760     void target(bool Foo) {
4761       bool Bar = true;
4762       do {
4763         (void)0;
4764         // [[loop_body]]
4765         Bar = false;
4766       } while (Foo);
4767       (void)0;
4768       // [[after_loop]]
4769     }
4770   )";
4771   runDataflow(
4772       Code,
4773       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4774          ASTContext &ASTCtx) {
4775         ASSERT_THAT(Results.keys(),
4776                     UnorderedElementsAre("loop_body", "after_loop"));
4777         const Environment &LoopBodyEnv =
4778             getEnvironmentAtAnnotation(Results, "loop_body");
4779         const Environment &AfterLoopEnv =
4780             getEnvironmentAtAnnotation(Results, "after_loop");
4781         auto &A = AfterLoopEnv.arena();
4782 
4783         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4784         ASSERT_THAT(FooDecl, NotNull());
4785 
4786         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4787         ASSERT_THAT(BarDecl, NotNull());
4788 
4789         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4790         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
4791         EXPECT_TRUE(
4792             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4793 
4794         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4795         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
4796         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
4797         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
4798       });
4799 }
4800 
4801 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4802   std::string Code = R"(
4803     void target(bool Foo) {
4804       for (; Foo;) {
4805         (void)0;
4806         // [[loop_body]]
4807       }
4808       (void)0;
4809       // [[after_loop]]
4810     }
4811   )";
4812   runDataflow(
4813       Code,
4814       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4815          ASTContext &ASTCtx) {
4816         ASSERT_THAT(Results.keys(),
4817                     UnorderedElementsAre("loop_body", "after_loop"));
4818         const Environment &LoopBodyEnv =
4819             getEnvironmentAtAnnotation(Results, "loop_body");
4820         const Environment &AfterLoopEnv =
4821             getEnvironmentAtAnnotation(Results, "after_loop");
4822 
4823         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4824         ASSERT_THAT(FooDecl, NotNull());
4825 
4826         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4827         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4828 
4829         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4830         EXPECT_TRUE(
4831             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4832       });
4833 }
4834 
4835 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4836   std::string Code = R"(
4837     void target(bool Foo) {
4838       for (;;) {
4839         (void)0;
4840         // [[loop_body]]
4841       }
4842     }
4843   )";
4844   runDataflow(
4845       Code,
4846       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4847          ASTContext &ASTCtx) {
4848         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4849         const Environment &LoopBodyEnv =
4850             getEnvironmentAtAnnotation(Results, "loop_body");
4851 
4852         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4853         ASSERT_THAT(FooDecl, NotNull());
4854 
4855         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4856         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
4857       });
4858 }
4859 
4860 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4861   std::string Code = R"(
4862     bool GiveBool();
4863     void SetBool(bool &Var) { Var = true; }
4864 
4865     void target() {
4866       bool Foo = GiveBool();
4867       SetBool(Foo);
4868       // [[p]]
4869     }
4870   )";
4871   runDataflow(
4872       Code,
4873       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4874          ASTContext &ASTCtx) {
4875         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4876         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4877 
4878         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4879         ASSERT_THAT(FooDecl, NotNull());
4880 
4881         auto &FooVal = getFormula(*FooDecl, Env);
4882         EXPECT_FALSE(Env.proves(FooVal));
4883         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
4884       },
4885       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4886 }
4887 
4888 TEST(TransferTest, ContextSensitiveReturnReference) {
4889   std::string Code = R"(
4890     class S {};
4891     S& target(bool b, S &s) {
4892       return s;
4893       // [[p]]
4894     }
4895   )";
4896   runDataflow(
4897       Code,
4898       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4899          ASTContext &ASTCtx) {
4900         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4901 
4902         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4903         ASSERT_THAT(SDecl, NotNull());
4904 
4905         auto *SLoc = Env.getStorageLocation(*SDecl);
4906         ASSERT_THAT(SLoc, NotNull());
4907 
4908         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4909       },
4910       {BuiltinOptions{ContextSensitiveOptions{}}});
4911 }
4912 
4913 // This test is a regression test, based on a real crash.
4914 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4915   std::string Code = R"(
4916     class S {};
4917     S& target(bool b, S &s) {
4918       return b ? s : s;
4919       // [[p]]
4920     }
4921   )";
4922   runDataflow(
4923       Code,
4924       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4925          ASTContext &ASTCtx) {
4926         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4927         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4928 
4929         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4930         ASSERT_THAT(SDecl, NotNull());
4931 
4932         auto *SLoc = Env.getStorageLocation(*SDecl);
4933         ASSERT_THAT(SLoc, NotNull());
4934         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4935 
4936         auto *Loc = Env.getReturnStorageLocation();
4937         ASSERT_THAT(Loc, NotNull());
4938         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4939 
4940         // TODO: We would really like to make this stronger assertion, but that
4941         // doesn't work because we don't propagate values correctly through
4942         // the conditional operator yet.
4943         // ASSERT_THAT(Loc, Eq(SLoc));
4944       },
4945       {BuiltinOptions{ContextSensitiveOptions{}}});
4946 }
4947 
4948 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4949   std::string Code = R"(
4950     class S {};
4951     S &callee(bool b, S &s1_parm, S &s2_parm) {
4952       if (b)
4953         return s1_parm;
4954       else
4955         return s2_parm;
4956     }
4957     void target(bool b) {
4958       S s1;
4959       S s2;
4960       S &return_s1 = s1;
4961       S &return_s2 = s2;
4962       S &return_dont_know = callee(b, s1, s2);
4963       // [[p]]
4964     }
4965   )";
4966   runDataflow(
4967       Code,
4968       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4969          ASTContext &ASTCtx) {
4970         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4971 
4972         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4973         ASSERT_THAT(S1, NotNull());
4974         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4975         ASSERT_THAT(S2, NotNull());
4976         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4977         ASSERT_THAT(ReturnS1, NotNull());
4978         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4979         ASSERT_THAT(ReturnS2, NotNull());
4980         const ValueDecl *ReturnDontKnow =
4981             findValueDecl(ASTCtx, "return_dont_know");
4982         ASSERT_THAT(ReturnDontKnow, NotNull());
4983 
4984         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4985         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4986 
4987         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4988         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4989 
4990         // In the case where we don't have a consistent storage location for
4991         // the return value, the framework creates a new storage location, which
4992         // should be different from the storage locations of `s1` and `s2`.
4993         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4994         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4995       },
4996       {BuiltinOptions{ContextSensitiveOptions{}}});
4997 }
4998 
4999 TEST(TransferTest, ContextSensitiveDepthZero) {
5000   std::string Code = R"(
5001     bool GiveBool();
5002     void SetBool(bool &Var) { Var = true; }
5003 
5004     void target() {
5005       bool Foo = GiveBool();
5006       SetBool(Foo);
5007       // [[p]]
5008     }
5009   )";
5010   runDataflow(
5011       Code,
5012       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5013          ASTContext &ASTCtx) {
5014         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5015         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5016 
5017         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5018         ASSERT_THAT(FooDecl, NotNull());
5019 
5020         auto &FooVal = getFormula(*FooDecl, Env);
5021         EXPECT_FALSE(Env.proves(FooVal));
5022         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5023       },
5024       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
5025 }
5026 
5027 TEST(TransferTest, ContextSensitiveSetTrue) {
5028   std::string Code = R"(
5029     bool GiveBool();
5030     void SetBool(bool &Var) { Var = true; }
5031 
5032     void target() {
5033       bool Foo = GiveBool();
5034       SetBool(Foo);
5035       // [[p]]
5036     }
5037   )";
5038   runDataflow(
5039       Code,
5040       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5041          ASTContext &ASTCtx) {
5042         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5043         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5044 
5045         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5046         ASSERT_THAT(FooDecl, NotNull());
5047 
5048         auto &FooVal = getFormula(*FooDecl, Env);
5049         EXPECT_TRUE(Env.proves(FooVal));
5050       },
5051       {BuiltinOptions{ContextSensitiveOptions{}}});
5052 }
5053 
5054 TEST(TransferTest, ContextSensitiveSetFalse) {
5055   std::string Code = R"(
5056     bool GiveBool();
5057     void SetBool(bool &Var) { Var = false; }
5058 
5059     void target() {
5060       bool Foo = GiveBool();
5061       SetBool(Foo);
5062       // [[p]]
5063     }
5064   )";
5065   runDataflow(
5066       Code,
5067       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5068          ASTContext &ASTCtx) {
5069         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5070         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5071 
5072         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5073         ASSERT_THAT(FooDecl, NotNull());
5074 
5075         auto &FooVal = getFormula(*FooDecl, Env);
5076         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5077       },
5078       {BuiltinOptions{ContextSensitiveOptions{}}});
5079 }
5080 
5081 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5082   std::string Code = R"(
5083     bool GiveBool();
5084     void SetBool(bool &Var, bool Val) { Var = Val; }
5085 
5086     void target() {
5087       bool Foo = GiveBool();
5088       bool Bar = GiveBool();
5089       SetBool(Foo, true);
5090       SetBool(Bar, false);
5091       // [[p]]
5092     }
5093   )";
5094   runDataflow(
5095       Code,
5096       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5097          ASTContext &ASTCtx) {
5098         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5099         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5100         auto &A = Env.arena();
5101 
5102         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5103         ASSERT_THAT(FooDecl, NotNull());
5104 
5105         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5106         ASSERT_THAT(BarDecl, NotNull());
5107 
5108         auto &FooVal = getFormula(*FooDecl, Env);
5109         EXPECT_TRUE(Env.proves(FooVal));
5110         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
5111 
5112         auto &BarVal = getFormula(*BarDecl, Env);
5113         EXPECT_FALSE(Env.proves(BarVal));
5114         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
5115       },
5116       {BuiltinOptions{ContextSensitiveOptions{}}});
5117 }
5118 
5119 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
5120   std::string Code = R"(
5121     bool GiveBool();
5122     void SetBool1(bool &Var) { Var = true; }
5123     void SetBool2(bool &Var) { SetBool1(Var); }
5124 
5125     void target() {
5126       bool Foo = GiveBool();
5127       SetBool2(Foo);
5128       // [[p]]
5129     }
5130   )";
5131   runDataflow(
5132       Code,
5133       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5134          ASTContext &ASTCtx) {
5135         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5136         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5137 
5138         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5139         ASSERT_THAT(FooDecl, NotNull());
5140 
5141         auto &FooVal = getFormula(*FooDecl, Env);
5142         EXPECT_FALSE(Env.proves(FooVal));
5143         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5144       },
5145       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5146 }
5147 
5148 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5149   std::string Code = R"(
5150     bool GiveBool();
5151     void SetBool1(bool &Var) { Var = true; }
5152     void SetBool2(bool &Var) { SetBool1(Var); }
5153 
5154     void target() {
5155       bool Foo = GiveBool();
5156       SetBool2(Foo);
5157       // [[p]]
5158     }
5159   )";
5160   runDataflow(
5161       Code,
5162       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5163          ASTContext &ASTCtx) {
5164         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5165         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5166 
5167         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5168         ASSERT_THAT(FooDecl, NotNull());
5169 
5170         auto &FooVal = getFormula(*FooDecl, Env);
5171         EXPECT_TRUE(Env.proves(FooVal));
5172       },
5173       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5174 }
5175 
5176 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5177   std::string Code = R"(
5178     bool GiveBool();
5179     void SetBool1(bool &Var) { Var = true; }
5180     void SetBool2(bool &Var) { SetBool1(Var); }
5181     void SetBool3(bool &Var) { SetBool2(Var); }
5182 
5183     void target() {
5184       bool Foo = GiveBool();
5185       SetBool3(Foo);
5186       // [[p]]
5187     }
5188   )";
5189   runDataflow(
5190       Code,
5191       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5192          ASTContext &ASTCtx) {
5193         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5194         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5195 
5196         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5197         ASSERT_THAT(FooDecl, NotNull());
5198 
5199         auto &FooVal = getFormula(*FooDecl, Env);
5200         EXPECT_FALSE(Env.proves(FooVal));
5201         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5202       },
5203       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5204 }
5205 
5206 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5207   std::string Code = R"(
5208     bool GiveBool();
5209     void SetBool1(bool &Var) { Var = true; }
5210     void SetBool2(bool &Var) { SetBool1(Var); }
5211     void SetBool3(bool &Var) { SetBool2(Var); }
5212 
5213     void target() {
5214       bool Foo = GiveBool();
5215       SetBool3(Foo);
5216       // [[p]]
5217     }
5218   )";
5219   runDataflow(
5220       Code,
5221       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5222          ASTContext &ASTCtx) {
5223         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5224         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5225 
5226         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5227         ASSERT_THAT(FooDecl, NotNull());
5228 
5229         auto &FooVal = getFormula(*FooDecl, Env);
5230         EXPECT_TRUE(Env.proves(FooVal));
5231       },
5232       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5233 }
5234 
5235 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5236   std::string Code = R"(
5237     bool Pong(bool X, bool Y);
5238 
5239     bool Ping(bool X, bool Y) {
5240       if (X) {
5241         return Y;
5242       } else {
5243         return Pong(!X, Y);
5244       }
5245     }
5246 
5247     bool Pong(bool X, bool Y) {
5248       if (Y) {
5249         return X;
5250       } else {
5251         return Ping(X, !Y);
5252       }
5253     }
5254 
5255     void target() {
5256       bool Foo = Ping(false, false);
5257       // [[p]]
5258     }
5259   )";
5260   runDataflow(
5261       Code,
5262       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5263          ASTContext &ASTCtx) {
5264         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5265         // The analysis doesn't crash...
5266         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5267 
5268         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5269         ASSERT_THAT(FooDecl, NotNull());
5270 
5271         auto &FooVal = getFormula(*FooDecl, Env);
5272         // ... but it also can't prove anything here.
5273         EXPECT_FALSE(Env.proves(FooVal));
5274         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5275       },
5276       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5277 }
5278 
5279 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5280   std::string Code = R"(
5281     void SetBools(bool &Var1, bool &Var2) {
5282       Var1 = true;
5283       Var2 = false;
5284     }
5285 
5286     void target() {
5287       bool Foo = false;
5288       bool Bar = true;
5289       SetBools(Foo, Bar);
5290       // [[p]]
5291     }
5292   )";
5293   runDataflow(
5294       Code,
5295       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5296          ASTContext &ASTCtx) {
5297         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5298         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5299 
5300         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5301         ASSERT_THAT(FooDecl, NotNull());
5302 
5303         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5304         ASSERT_THAT(BarDecl, NotNull());
5305 
5306         auto &FooVal = getFormula(*FooDecl, Env);
5307         EXPECT_TRUE(Env.proves(FooVal));
5308         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5309 
5310         auto &BarVal = getFormula(*BarDecl, Env);
5311         EXPECT_FALSE(Env.proves(BarVal));
5312         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5313       },
5314       {BuiltinOptions{ContextSensitiveOptions{}}});
5315 }
5316 
5317 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5318   std::string Code = R"(
5319     void IfCond(bool Cond, bool &Then, bool &Else) {
5320       if (Cond) {
5321         Then = true;
5322       } else {
5323         Else = true;
5324       }
5325     }
5326 
5327     void target() {
5328       bool Foo = false;
5329       bool Bar = false;
5330       bool Baz = false;
5331       IfCond(Foo, Bar, Baz);
5332       // [[p]]
5333     }
5334   )";
5335   runDataflow(
5336       Code,
5337       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5338          ASTContext &ASTCtx) {
5339         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5340         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5341 
5342         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5343         ASSERT_THAT(BarDecl, NotNull());
5344 
5345         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5346         ASSERT_THAT(BazDecl, NotNull());
5347 
5348         auto &BarVal = getFormula(*BarDecl, Env);
5349         EXPECT_FALSE(Env.proves(BarVal));
5350         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5351 
5352         auto &BazVal = getFormula(*BazDecl, Env);
5353         EXPECT_TRUE(Env.proves(BazVal));
5354         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5355       },
5356       {BuiltinOptions{ContextSensitiveOptions{}}});
5357 }
5358 
5359 TEST(TransferTest, ContextSensitiveReturnVoid) {
5360   std::string Code = R"(
5361     void Noop() { return; }
5362 
5363     void target() {
5364       Noop();
5365       // [[p]]
5366     }
5367   )";
5368   runDataflow(
5369       Code,
5370       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5371          ASTContext &ASTCtx) {
5372         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5373         // This just tests that the analysis doesn't crash.
5374       },
5375       {BuiltinOptions{ContextSensitiveOptions{}}});
5376 }
5377 
5378 TEST(TransferTest, ContextSensitiveReturnTrue) {
5379   std::string Code = R"(
5380     bool GiveBool() { return true; }
5381 
5382     void target() {
5383       bool Foo = GiveBool();
5384       // [[p]]
5385     }
5386   )";
5387   runDataflow(
5388       Code,
5389       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5390          ASTContext &ASTCtx) {
5391         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5392         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5393 
5394         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5395         ASSERT_THAT(FooDecl, NotNull());
5396 
5397         auto &FooVal = getFormula(*FooDecl, Env);
5398         EXPECT_TRUE(Env.proves(FooVal));
5399       },
5400       {BuiltinOptions{ContextSensitiveOptions{}}});
5401 }
5402 
5403 TEST(TransferTest, ContextSensitiveReturnFalse) {
5404   std::string Code = R"(
5405     bool GiveBool() { return false; }
5406 
5407     void target() {
5408       bool Foo = GiveBool();
5409       // [[p]]
5410     }
5411   )";
5412   runDataflow(
5413       Code,
5414       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5415          ASTContext &ASTCtx) {
5416         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5417         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5418 
5419         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5420         ASSERT_THAT(FooDecl, NotNull());
5421 
5422         auto &FooVal = getFormula(*FooDecl, Env);
5423         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5424       },
5425       {BuiltinOptions{ContextSensitiveOptions{}}});
5426 }
5427 
5428 TEST(TransferTest, ContextSensitiveReturnArg) {
5429   std::string Code = R"(
5430     bool GiveBool();
5431     bool GiveBack(bool Arg) { return Arg; }
5432 
5433     void target() {
5434       bool Foo = GiveBool();
5435       bool Bar = GiveBack(Foo);
5436       bool Baz = Foo == Bar;
5437       // [[p]]
5438     }
5439   )";
5440   runDataflow(
5441       Code,
5442       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5443          ASTContext &ASTCtx) {
5444         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5445         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5446 
5447         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5448         ASSERT_THAT(BazDecl, NotNull());
5449 
5450         auto &BazVal = getFormula(*BazDecl, Env);
5451         EXPECT_TRUE(Env.proves(BazVal));
5452       },
5453       {BuiltinOptions{ContextSensitiveOptions{}}});
5454 }
5455 
5456 TEST(TransferTest, ContextSensitiveReturnInt) {
5457   std::string Code = R"(
5458     int identity(int x) { return x; }
5459 
5460     void target() {
5461       int y = identity(42);
5462       // [[p]]
5463     }
5464   )";
5465   runDataflow(
5466       Code,
5467       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5468          ASTContext &ASTCtx) {
5469         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5470         // This just tests that the analysis doesn't crash.
5471       },
5472       {BuiltinOptions{ContextSensitiveOptions{}}});
5473 }
5474 
5475 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5476   std::string Code = R"(
5477     class MyClass {
5478     public:
5479       bool giveBool() { return true; }
5480     };
5481 
5482     void target() {
5483       MyClass MyObj;
5484       bool Foo = MyObj.giveBool();
5485       // [[p]]
5486     }
5487   )";
5488   runDataflow(
5489       Code,
5490       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5491          ASTContext &ASTCtx) {
5492         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5493         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5494 
5495         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5496         ASSERT_THAT(FooDecl, NotNull());
5497 
5498         auto &FooVal = getFormula(*FooDecl, Env);
5499         EXPECT_TRUE(Env.proves(FooVal));
5500       },
5501       {BuiltinOptions{ContextSensitiveOptions{}}});
5502 }
5503 
5504 TEST(TransferTest, ContextSensitiveMethodGetter) {
5505   std::string Code = R"(
5506     class MyClass {
5507     public:
5508       bool getField() { return Field; }
5509 
5510       bool Field;
5511     };
5512 
5513     void target() {
5514       MyClass MyObj;
5515       MyObj.Field = true;
5516       bool Foo = MyObj.getField();
5517       // [[p]]
5518     }
5519   )";
5520   runDataflow(
5521       Code,
5522       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5523          ASTContext &ASTCtx) {
5524         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5525         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5526 
5527         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5528         ASSERT_THAT(FooDecl, NotNull());
5529 
5530         auto &FooVal = getFormula(*FooDecl, Env);
5531         EXPECT_TRUE(Env.proves(FooVal));
5532       },
5533       {BuiltinOptions{ContextSensitiveOptions{}}});
5534 }
5535 
5536 TEST(TransferTest, ContextSensitiveMethodSetter) {
5537   std::string Code = R"(
5538     class MyClass {
5539     public:
5540       void setField(bool Val) { Field = Val; }
5541 
5542       bool Field;
5543     };
5544 
5545     void target() {
5546       MyClass MyObj;
5547       MyObj.setField(true);
5548       bool Foo = MyObj.Field;
5549       // [[p]]
5550     }
5551   )";
5552   runDataflow(
5553       Code,
5554       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5555          ASTContext &ASTCtx) {
5556         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5557         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5558 
5559         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5560         ASSERT_THAT(FooDecl, NotNull());
5561 
5562         auto &FooVal = getFormula(*FooDecl, Env);
5563         EXPECT_TRUE(Env.proves(FooVal));
5564       },
5565       {BuiltinOptions{ContextSensitiveOptions{}}});
5566 }
5567 
5568 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5569   std::string Code = R"(
5570     class MyClass {
5571     public:
5572       bool getField() { return Field; }
5573       void setField(bool Val) { Field = Val; }
5574 
5575     private:
5576       bool Field;
5577     };
5578 
5579     void target() {
5580       MyClass MyObj;
5581       MyObj.setField(true);
5582       bool Foo = MyObj.getField();
5583       // [[p]]
5584     }
5585   )";
5586   runDataflow(
5587       Code,
5588       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5589          ASTContext &ASTCtx) {
5590         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5591         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5592 
5593         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5594         ASSERT_THAT(FooDecl, NotNull());
5595 
5596         auto &FooVal = getFormula(*FooDecl, Env);
5597         EXPECT_TRUE(Env.proves(FooVal));
5598       },
5599       {BuiltinOptions{ContextSensitiveOptions{}}});
5600 }
5601 
5602 
5603 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5604   std::string Code = R"(
5605     class MyClass {
5606     public:
5607       void Inner() { MyField = true; }
5608       void Outer() { Inner(); }
5609 
5610       bool MyField;
5611     };
5612 
5613     void target() {
5614       MyClass MyObj;
5615       MyObj.Outer();
5616       bool Foo = MyObj.MyField;
5617       // [[p]]
5618     }
5619   )";
5620   runDataflow(
5621       Code,
5622       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5623          ASTContext &ASTCtx) {
5624         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5625         ;
5626         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5627 
5628         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5629         ASSERT_THAT(FooDecl, NotNull());
5630 
5631         auto &FooVal = getFormula(*FooDecl, Env);
5632         EXPECT_TRUE(Env.proves(FooVal));
5633       },
5634       {BuiltinOptions{ContextSensitiveOptions{}}});
5635 }
5636 
5637 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5638   std::string Code = R"(
5639     class MyClass {
5640     public:
5641       bool Inner() { return MyField; }
5642       bool Outer() { return Inner(); }
5643 
5644       bool MyField;
5645     };
5646 
5647     void target() {
5648       MyClass MyObj;
5649       MyObj.MyField = true;
5650       bool Foo = MyObj.Outer();
5651       // [[p]]
5652     }
5653   )";
5654   runDataflow(
5655       Code,
5656       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5657          ASTContext &ASTCtx) {
5658         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5659         ;
5660         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5661 
5662         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5663         ASSERT_THAT(FooDecl, NotNull());
5664 
5665         auto &FooVal = getFormula(*FooDecl, Env);
5666         EXPECT_TRUE(Env.proves(FooVal));
5667       },
5668       {BuiltinOptions{ContextSensitiveOptions{}}});
5669 }
5670 
5671 TEST(TransferTest, ContextSensitiveConstructorBody) {
5672   std::string Code = R"(
5673     class MyClass {
5674     public:
5675       MyClass() { MyField = true; }
5676 
5677       bool MyField;
5678     };
5679 
5680     void target() {
5681       MyClass MyObj;
5682       bool Foo = MyObj.MyField;
5683       // [[p]]
5684     }
5685   )";
5686   runDataflow(
5687       Code,
5688       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5689          ASTContext &ASTCtx) {
5690         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5691         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5692 
5693         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5694         ASSERT_THAT(FooDecl, NotNull());
5695 
5696         auto &FooVal = getFormula(*FooDecl, Env);
5697         EXPECT_TRUE(Env.proves(FooVal));
5698       },
5699       {BuiltinOptions{ContextSensitiveOptions{}}});
5700 }
5701 
5702 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5703   std::string Code = R"(
5704     class MyClass {
5705     public:
5706       MyClass() : MyField(true) {}
5707 
5708       bool MyField;
5709     };
5710 
5711     void target() {
5712       MyClass MyObj;
5713       bool Foo = MyObj.MyField;
5714       // [[p]]
5715     }
5716   )";
5717   runDataflow(
5718       Code,
5719       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5720          ASTContext &ASTCtx) {
5721         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5722         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5723 
5724         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5725         ASSERT_THAT(FooDecl, NotNull());
5726 
5727         auto &FooVal = getFormula(*FooDecl, Env);
5728         EXPECT_TRUE(Env.proves(FooVal));
5729       },
5730       {BuiltinOptions{ContextSensitiveOptions{}}});
5731 }
5732 
5733 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5734   std::string Code = R"(
5735     class MyClass {
5736     public:
5737       MyClass() = default;
5738 
5739       bool MyField = true;
5740     };
5741 
5742     void target() {
5743       MyClass MyObj;
5744       bool Foo = MyObj.MyField;
5745       // [[p]]
5746     }
5747   )";
5748   runDataflow(
5749       Code,
5750       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5751          ASTContext &ASTCtx) {
5752         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5753         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5754 
5755         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5756         ASSERT_THAT(FooDecl, NotNull());
5757 
5758         auto &FooVal = getFormula(*FooDecl, Env);
5759         EXPECT_TRUE(Env.proves(FooVal));
5760       },
5761       {BuiltinOptions{ContextSensitiveOptions{}}});
5762 }
5763 
5764 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
5765   // Test that the `this` pointer seen in the constructor has the same value
5766   // as the address of the variable the object is constructed into.
5767   std::string Code = R"(
5768     class MyClass {
5769     public:
5770       MyClass() : Self(this) {}
5771       MyClass *Self;
5772     };
5773 
5774     void target() {
5775       MyClass MyObj;
5776       MyClass *SelfPtr = MyObj.Self;
5777       // [[p]]
5778     }
5779   )";
5780   runDataflow(
5781       Code,
5782       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5783          ASTContext &ASTCtx) {
5784         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5785 
5786         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
5787         ASSERT_THAT(MyObjDecl, NotNull());
5788 
5789         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
5790         ASSERT_THAT(SelfDecl, NotNull());
5791 
5792         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5793         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
5794         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
5795       },
5796       {BuiltinOptions{ContextSensitiveOptions{}}});
5797 }
5798 
5799 TEST(TransferTest, UnnamedBitfieldInitializer) {
5800   std::string Code = R"(
5801     struct B {};
5802     struct A {
5803       unsigned a;
5804       unsigned : 4;
5805       unsigned c;
5806       B b;
5807     };
5808     void target() {
5809       A a = {};
5810       A test = a;
5811       (void)test.c;
5812     }
5813   )";
5814   runDataflow(
5815       Code,
5816       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5817          ASTContext &ASTCtx) {
5818         // This doesn't need a body because this test was crashing the framework
5819         // before handling correctly Unnamed bitfields in `InitListExpr`.
5820       });
5821 }
5822 
5823 // Repro for a crash that used to occur with chained short-circuiting logical
5824 // operators.
5825 TEST(TransferTest, ChainedLogicalOps) {
5826   std::string Code = R"(
5827     bool target() {
5828       bool b = true || false || false || false;
5829       // [[p]]
5830       return b;
5831     }
5832   )";
5833   runDataflow(
5834       Code,
5835       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5836          ASTContext &ASTCtx) {
5837         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5838         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
5839         EXPECT_TRUE(Env.proves(B));
5840       });
5841 }
5842 
5843 // Repro for a crash that used to occur when we call a `noreturn` function
5844 // within one of the operands of a `&&` or `||` operator.
5845 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5846   std::string Code = R"(
5847     __attribute__((noreturn)) int doesnt_return();
5848     bool some_condition();
5849     void target(bool b1, bool b2) {
5850       // Neither of these should crash. In addition, if we don't terminate the
5851       // program, we know that the operators need to trigger the short-circuit
5852       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5853       // will be true.
5854       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5855       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5856 
5857       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5858       // entire expression unreachable. So we know that in both of the following
5859       // cases, if `target()` terminates, the `else` branch was taken.
5860       bool NoreturnOnLhsMakesAndUnreachable = false;
5861       if (some_condition())
5862          doesnt_return() > 0 && some_condition();
5863       else
5864          NoreturnOnLhsMakesAndUnreachable = true;
5865 
5866       bool NoreturnOnLhsMakesOrUnreachable = false;
5867       if (some_condition())
5868          doesnt_return() > 0 || some_condition();
5869       else
5870          NoreturnOnLhsMakesOrUnreachable = true;
5871 
5872       // [[p]]
5873     }
5874   )";
5875   runDataflow(
5876       Code,
5877       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5878          ASTContext &ASTCtx) {
5879         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5880         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5881         auto &A = Env.arena();
5882 
5883         // Check that [[p]] is reachable with a non-false flow condition.
5884         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
5885 
5886         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
5887         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
5888 
5889         auto &NoreturnOnRhsOfAnd =
5890             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
5891         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
5892 
5893         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
5894         EXPECT_TRUE(Env.proves(B2));
5895 
5896         auto &NoreturnOnRhsOfOr =
5897             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
5898                 .formula();
5899         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
5900 
5901         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5902             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
5903         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
5904 
5905         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5906             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
5907         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
5908       });
5909 }
5910 
5911 TEST(TransferTest, NewExpressions) {
5912   std::string Code = R"(
5913     void target() {
5914       int *p = new int(42);
5915       // [[after_new]]
5916     }
5917   )";
5918   runDataflow(
5919       Code,
5920       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5921          ASTContext &ASTCtx) {
5922         const Environment &Env =
5923             getEnvironmentAtAnnotation(Results, "after_new");
5924 
5925         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5926 
5927         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5928       });
5929 }
5930 
5931 TEST(TransferTest, NewExpressions_Structs) {
5932   std::string Code = R"(
5933     struct Inner {
5934       int InnerField;
5935     };
5936 
5937     struct Outer {
5938       Inner OuterField;
5939     };
5940 
5941     void target() {
5942       Outer *p = new Outer;
5943       // Access the fields to make sure the analysis actually generates children
5944       // for them in the `RecordStorageLocation` and `RecordValue`.
5945       p->OuterField.InnerField;
5946       // [[after_new]]
5947     }
5948   )";
5949   runDataflow(
5950       Code,
5951       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5952          ASTContext &ASTCtx) {
5953         const Environment &Env =
5954             getEnvironmentAtAnnotation(Results, "after_new");
5955 
5956         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5957         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5958 
5959         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5960 
5961         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
5962         auto &OuterFieldLoc =
5963             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
5964         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
5965 
5966         // Values for the struct and all fields exist after the new.
5967         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5968         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5969         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5970       });
5971 }
5972 
5973 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5974   std::string Code = R"(
5975     struct A { static void static_member_func(); };
5976     void target() {
5977       // To check that we're treating function-to-pointer decay correctly,
5978       // create two pointers, then verify they refer to the same storage
5979       // location.
5980       // We need to do the test this way because even if an initializer (in this
5981       // case, the function-to-pointer decay) does not create a value, we still
5982       // create a value for the variable.
5983       void (*non_member_p1)() = target;
5984       void (*non_member_p2)() = target;
5985 
5986       // Do the same thing but for a static member function.
5987       void (*member_p1)() = A::static_member_func;
5988       void (*member_p2)() = A::static_member_func;
5989       // [[p]]
5990     }
5991   )";
5992   runDataflow(
5993       Code,
5994       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5995          ASTContext &ASTCtx) {
5996         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5997 
5998         auto &NonMemberP1 =
5999             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
6000         auto &NonMemberP2 =
6001             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
6002         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
6003 
6004         auto &MemberP1 =
6005             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
6006         auto &MemberP2 =
6007             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
6008         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
6009       });
6010 }
6011 
6012 // Check that a builtin function is not associated with a value. (It's only
6013 // possible to call builtin functions directly, not take their address.)
6014 TEST(TransferTest, BuiltinFunctionModeled) {
6015   std::string Code = R"(
6016     void target() {
6017       __builtin_expect(0, 0);
6018       // [[p]]
6019     }
6020   )";
6021   runDataflow(
6022       Code,
6023       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6024          ASTContext &ASTCtx) {
6025         using ast_matchers::selectFirst;
6026         using ast_matchers::match;
6027         using ast_matchers::traverse;
6028         using ast_matchers::implicitCastExpr;
6029         using ast_matchers::hasCastKind;
6030 
6031         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6032 
6033         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
6034             "implicit_cast",
6035             match(traverse(TK_AsIs,
6036                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
6037                                .bind("implicit_cast")),
6038                   ASTCtx));
6039 
6040         ASSERT_THAT(ImplicitCast, NotNull());
6041         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
6042       });
6043 }
6044 
6045 // Check that a callee of a member operator call is modeled as a `PointerValue`.
6046 // Member operator calls are unusual in that their callee is a pointer that
6047 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
6048 // member functions, the callee is a `MemberExpr` (which does not have pointer
6049 // type).
6050 // We want to make sure that we produce a pointer value for the callee in this
6051 // specific scenario and that its storage location is durable (for convergence).
6052 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
6053   std::string Code = R"(
6054     struct S {
6055       bool operator!=(S s);
6056     };
6057     void target() {
6058       S s;
6059       (void)(s != s);
6060       (void)(s != s);
6061       // [[p]]
6062     }
6063   )";
6064   runDataflow(
6065       Code,
6066       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6067          ASTContext &ASTCtx) {
6068         using ast_matchers::selectFirst;
6069         using ast_matchers::match;
6070         using ast_matchers::traverse;
6071         using ast_matchers::cxxOperatorCallExpr;
6072 
6073         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6074 
6075         auto Matches = match(
6076             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
6077 
6078         ASSERT_EQ(Matches.size(), 2UL);
6079 
6080         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
6081         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
6082 
6083         ASSERT_THAT(Call1, NotNull());
6084         ASSERT_THAT(Call2, NotNull());
6085 
6086         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
6087                   CK_FunctionToPointerDecay);
6088         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
6089                   CK_FunctionToPointerDecay);
6090 
6091         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
6092         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
6093 
6094         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
6095       });
6096 }
6097 
6098 // Check that fields of anonymous records are modeled.
6099 TEST(TransferTest, AnonymousStruct) {
6100   std::string Code = R"(
6101     struct S {
6102       struct {
6103         bool b;
6104       };
6105     };
6106     void target() {
6107       S s;
6108       s.b = true;
6109       // [[p]]
6110     }
6111   )";
6112   runDataflow(
6113       Code,
6114       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6115          ASTContext &ASTCtx) {
6116         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6117         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
6118         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6119         const IndirectFieldDecl *IndirectField =
6120             findIndirectFieldDecl(ASTCtx, "b");
6121 
6122         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
6123         auto &AnonStruct = *cast<RecordStorageLocation>(
6124             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
6125 
6126         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6127         ASSERT_TRUE(Env.proves(B->formula()));
6128       });
6129 }
6130 
6131 TEST(TransferTest, AnonymousStructWithInitializer) {
6132   std::string Code = R"(
6133     struct target {
6134       target() {
6135         (void)0;
6136         // [[p]]
6137       }
6138       struct {
6139         bool b = true;
6140       };
6141     };
6142   )";
6143   runDataflow(
6144       Code,
6145       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6146          ASTContext &ASTCtx) {
6147         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6148         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6149         const IndirectFieldDecl *IndirectField =
6150             findIndirectFieldDecl(ASTCtx, "b");
6151 
6152         auto *ThisLoc =
6153             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6154         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6155             *cast<ValueDecl>(IndirectField->chain().front())));
6156 
6157         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6158         ASSERT_TRUE(Env.proves(B->formula()));
6159       });
6160 }
6161 
6162 TEST(TransferTest, AnonymousStructWithReferenceField) {
6163   std::string Code = R"(
6164     int global_i = 0;
6165     struct target {
6166       target() {
6167         (void)0;
6168         // [[p]]
6169       }
6170       struct {
6171         int &i = global_i;
6172       };
6173     };
6174   )";
6175   runDataflow(
6176       Code,
6177       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6178          ASTContext &ASTCtx) {
6179         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6180         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6181         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6182         const IndirectFieldDecl *IndirectField =
6183             findIndirectFieldDecl(ASTCtx, "i");
6184 
6185         auto *ThisLoc =
6186             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6187         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6188             *cast<ValueDecl>(IndirectField->chain().front())));
6189 
6190         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6191                   Env.getStorageLocation(*GlobalIDecl));
6192       });
6193 }
6194 
6195 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6196   // This is a crash repro.
6197   // `false` block may not have been processed when we try to evaluate the `||`
6198   // after visiting `true`, because it is not necessary (and therefore the edge
6199   // is marked unreachable). Trying to get the analysis state via
6200   // `getEnvironment` for the subexpression still should not crash.
6201   std::string Code = R"(
6202     int target(int i) {
6203       if ((i < 0 && true) || false) {
6204         return 0;
6205       }
6206       return 0;
6207     }
6208   )";
6209   runDataflow(
6210       Code,
6211       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6212          ASTContext &ASTCtx) {});
6213 }
6214 
6215 TEST(TransferTest, LambdaCaptureByCopy) {
6216   std::string Code = R"(
6217     void target(int Foo, int Bar) {
6218       [Foo]() {
6219         (void)0;
6220         // [[p]]
6221       }();
6222     }
6223   )";
6224   runDataflowOnLambda(
6225       Code,
6226       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6227          ASTContext &ASTCtx) {
6228         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6229         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6230 
6231         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6232         ASSERT_THAT(FooDecl, NotNull());
6233 
6234         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6235         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6236 
6237         const Value *FooVal = Env.getValue(*FooLoc);
6238         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6239 
6240         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6241         ASSERT_THAT(BarDecl, NotNull());
6242 
6243         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6244         EXPECT_THAT(BarLoc, IsNull());
6245       });
6246 }
6247 
6248 TEST(TransferTest, LambdaCaptureByReference) {
6249   std::string Code = R"(
6250     void target(int Foo, int Bar) {
6251       [&Foo]() {
6252         (void)0;
6253         // [[p]]
6254       }();
6255     }
6256   )";
6257   runDataflowOnLambda(
6258       Code,
6259       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6260          ASTContext &ASTCtx) {
6261         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6262         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6263 
6264         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6265         ASSERT_THAT(FooDecl, NotNull());
6266 
6267         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6268         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6269 
6270         const Value *FooVal = Env.getValue(*FooLoc);
6271         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6272 
6273         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6274         ASSERT_THAT(BarDecl, NotNull());
6275 
6276         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6277         EXPECT_THAT(BarLoc, IsNull());
6278       });
6279 }
6280 
6281 TEST(TransferTest, LambdaCaptureWithInitializer) {
6282   std::string Code = R"(
6283     void target(int Bar) {
6284       [Foo=Bar]() {
6285         (void)0;
6286         // [[p]]
6287       }();
6288     }
6289   )";
6290   runDataflowOnLambda(
6291       Code,
6292       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6293          ASTContext &ASTCtx) {
6294         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6295         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6296 
6297         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6298         ASSERT_THAT(FooDecl, NotNull());
6299 
6300         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6301         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6302 
6303         const Value *FooVal = Env.getValue(*FooLoc);
6304         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6305 
6306         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6307         ASSERT_THAT(BarDecl, NotNull());
6308 
6309         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6310         EXPECT_THAT(BarLoc, IsNull());
6311       });
6312 }
6313 
6314 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
6315   std::string Code = R"(
6316     void target(int Foo, int Bar) {
6317       [=]() {
6318         Foo;
6319         // [[p]]
6320       }();
6321     }
6322   )";
6323   runDataflowOnLambda(
6324       Code,
6325       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6326          ASTContext &ASTCtx) {
6327         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6328         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6329 
6330         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6331         ASSERT_THAT(FooDecl, NotNull());
6332 
6333         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6334         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6335 
6336         const Value *FooVal = Env.getValue(*FooLoc);
6337         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6338 
6339         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6340         ASSERT_THAT(BarDecl, NotNull());
6341 
6342         // There is no storage location for `Bar` because it isn't used in the
6343         // body of the lambda.
6344         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6345         EXPECT_THAT(BarLoc, IsNull());
6346       });
6347 }
6348 
6349 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
6350   std::string Code = R"(
6351     void target(int Foo, int Bar) {
6352       [&]() {
6353         Foo;
6354         // [[p]]
6355       }();
6356     }
6357   )";
6358   runDataflowOnLambda(
6359       Code,
6360       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6361          ASTContext &ASTCtx) {
6362         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6363         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6364 
6365         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6366         ASSERT_THAT(FooDecl, NotNull());
6367 
6368         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6369         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6370 
6371         const Value *FooVal = Env.getValue(*FooLoc);
6372         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6373 
6374         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6375         ASSERT_THAT(BarDecl, NotNull());
6376 
6377         // There is no storage location for `Bar` because it isn't used in the
6378         // body of the lambda.
6379         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6380         EXPECT_THAT(BarLoc, IsNull());
6381       });
6382 }
6383 
6384 TEST(TransferTest, LambdaCaptureThis) {
6385   std::string Code = R"(
6386     struct Bar {
6387       int Foo;
6388 
6389       void target() {
6390         [this]() {
6391           Foo;
6392           // [[p]]
6393         }();
6394       }
6395     };
6396   )";
6397   runDataflowOnLambda(
6398       Code,
6399       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6400          ASTContext &ASTCtx) {
6401         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6402         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6403 
6404         const RecordStorageLocation *ThisPointeeLoc =
6405             Env.getThisPointeeStorageLocation();
6406         ASSERT_THAT(ThisPointeeLoc, NotNull());
6407 
6408         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6409         ASSERT_THAT(FooDecl, NotNull());
6410 
6411         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
6412         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6413 
6414         const Value *FooVal = Env.getValue(*FooLoc);
6415         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6416       });
6417 }
6418 
6419 TEST(TransferTest, DifferentReferenceLocInJoin) {
6420   // This test triggers a case where the storage location for a reference-type
6421   // variable is different for two states being joined. We used to believe this
6422   // could not happen and therefore had an assertion disallowing this; this test
6423   // exists to demonstrate that we can handle this condition without a failing
6424   // assertion. See also the discussion here:
6425   // https://discourse.llvm.org/t/70086/6
6426   std::string Code = R"(
6427     namespace std {
6428       template <class T> struct initializer_list {
6429         const T* begin();
6430         const T* end();
6431       };
6432     }
6433 
6434     void target(char* p, char* end) {
6435       while (p != end) {
6436         if (*p == ' ') {
6437           p++;
6438           continue;
6439         }
6440 
6441         auto && range = {1, 2};
6442         for (auto b = range.begin(), e = range.end(); b != e; ++b) {
6443         }
6444         (void)0;
6445         // [[p]]
6446       }
6447     }
6448   )";
6449   runDataflow(
6450       Code,
6451       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6452          ASTContext &ASTCtx) {
6453         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6454 
6455         // Joining environments with different storage locations for the same
6456         // declaration results in the declaration being removed from the joined
6457         // environment.
6458         const ValueDecl *VD = findValueDecl(ASTCtx, "range");
6459         ASSERT_EQ(Env.getStorageLocation(*VD), nullptr);
6460       });
6461 }
6462 
6463 } // namespace
6464