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