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