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