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