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