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