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