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