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