xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 3001d6ddaa7809274e49b794cb7ec07d21da130e)
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, DoesNotCrashOnUnionThisExpr) {
4171   std::string Code = R"(
4172     union Union {
4173       int A;
4174       float B;
4175     };
4176 
4177     void foo() {
4178       Union A;
4179       Union B;
4180       A = B;
4181     }
4182   )";
4183   // This is a crash regression test when calling the transfer function on a
4184   // `CXXThisExpr` that refers to a union.
4185   runDataflow(
4186       Code,
4187       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4188          ASTContext &) {},
4189       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4190 }
4191 
4192 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4193   std::string Code = R"(
4194     struct A {
4195       int Foo;
4196       int Bar;
4197     };
4198 
4199     void target() {
4200       int Qux;
4201       A Baz;
4202       Baz.Foo = Qux;
4203       auto &FooRef = Baz.Foo;
4204       auto &BarRef = Baz.Bar;
4205       auto &[BoundFooRef, BoundBarRef] = Baz;
4206       // [[p]]
4207     }
4208   )";
4209   runDataflow(
4210       Code,
4211       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4212          ASTContext &ASTCtx) {
4213         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4214         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4215 
4216         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4217         ASSERT_THAT(FooRefDecl, NotNull());
4218 
4219         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4220         ASSERT_THAT(BarRefDecl, NotNull());
4221 
4222         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4223         ASSERT_THAT(QuxDecl, NotNull());
4224 
4225         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4226         ASSERT_THAT(BoundFooRefDecl, NotNull());
4227 
4228         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4229         ASSERT_THAT(BoundBarRefDecl, NotNull());
4230 
4231         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4232         ASSERT_THAT(FooRefLoc, NotNull());
4233 
4234         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4235         ASSERT_THAT(BarRefLoc, NotNull());
4236 
4237         const Value *QuxVal = Env.getValue(*QuxDecl);
4238         ASSERT_THAT(QuxVal, NotNull());
4239 
4240         const StorageLocation *BoundFooRefLoc =
4241             Env.getStorageLocation(*BoundFooRefDecl);
4242         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4243 
4244         const StorageLocation *BoundBarRefLoc =
4245             Env.getStorageLocation(*BoundBarRefDecl);
4246         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4247 
4248         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4249       });
4250 }
4251 
4252 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4253   std::string Code = R"(
4254     struct A {
4255       int &Foo;
4256       int &Bar;
4257     };
4258 
4259     void target(A Baz) {
4260       int Qux;
4261       Baz.Foo = Qux;
4262       auto &FooRef = Baz.Foo;
4263       auto &BarRef = Baz.Bar;
4264       auto &[BoundFooRef, BoundBarRef] = Baz;
4265       // [[p]]
4266     }
4267   )";
4268   runDataflow(
4269       Code,
4270       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4271          ASTContext &ASTCtx) {
4272         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4273         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4274 
4275         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4276         ASSERT_THAT(FooRefDecl, NotNull());
4277 
4278         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4279         ASSERT_THAT(BarRefDecl, NotNull());
4280 
4281         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4282         ASSERT_THAT(QuxDecl, NotNull());
4283 
4284         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4285         ASSERT_THAT(BoundFooRefDecl, NotNull());
4286 
4287         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4288         ASSERT_THAT(BoundBarRefDecl, NotNull());
4289 
4290         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4291         ASSERT_THAT(FooRefLoc, NotNull());
4292 
4293         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4294         ASSERT_THAT(BarRefLoc, NotNull());
4295 
4296         const Value *QuxVal = Env.getValue(*QuxDecl);
4297         ASSERT_THAT(QuxVal, NotNull());
4298 
4299         const StorageLocation *BoundFooRefLoc =
4300             Env.getStorageLocation(*BoundFooRefDecl);
4301         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4302 
4303         const StorageLocation *BoundBarRefLoc =
4304             Env.getStorageLocation(*BoundBarRefDecl);
4305         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4306 
4307         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4308       });
4309 }
4310 
4311 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4312   std::string Code = R"(
4313     struct A {
4314       int Foo;
4315       int Bar;
4316     };
4317 
4318     void target() {
4319       int Qux;
4320       A Baz;
4321       Baz.Foo = Qux;
4322       auto &FooRef = Baz.Foo;
4323       auto &BarRef = Baz.Bar;
4324       auto [BoundFoo, BoundBar] = Baz;
4325       // [[p]]
4326     }
4327   )";
4328   runDataflow(
4329       Code,
4330       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4331          ASTContext &ASTCtx) {
4332         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4333         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4334 
4335         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4336         ASSERT_THAT(FooRefDecl, NotNull());
4337 
4338         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4339         ASSERT_THAT(BarRefDecl, NotNull());
4340 
4341         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4342         ASSERT_THAT(BoundFooDecl, NotNull());
4343 
4344         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4345         ASSERT_THAT(BoundBarDecl, NotNull());
4346 
4347         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4348         ASSERT_THAT(QuxDecl, NotNull());
4349 
4350         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4351         ASSERT_THAT(FooRefLoc, NotNull());
4352 
4353         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4354         ASSERT_THAT(BarRefLoc, NotNull());
4355 
4356         const Value *QuxVal = Env.getValue(*QuxDecl);
4357         ASSERT_THAT(QuxVal, NotNull());
4358 
4359         const StorageLocation *BoundFooLoc =
4360             Env.getStorageLocation(*BoundFooDecl);
4361         EXPECT_NE(BoundFooLoc, FooRefLoc);
4362 
4363         const StorageLocation *BoundBarLoc =
4364             Env.getStorageLocation(*BoundBarDecl);
4365         EXPECT_NE(BoundBarLoc, BarRefLoc);
4366 
4367         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4368       });
4369 }
4370 
4371 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4372   std::string Code = R"(
4373     namespace std {
4374     using size_t = int;
4375     template <class> struct tuple_size;
4376     template <std::size_t, class> struct tuple_element;
4377     template <class...> class tuple;
4378 
4379     namespace {
4380     template <class T, T v>
4381     struct size_helper { static const T value = v; };
4382     } // namespace
4383 
4384     template <class... T>
4385     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4386 
4387     template <std::size_t I, class... T>
4388     struct tuple_element<I, tuple<T...>> {
4389       using type =  __type_pack_element<I, T...>;
4390     };
4391 
4392     template <class...> class tuple {};
4393 
4394     template <std::size_t I, class... T>
4395     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4396     } // namespace std
4397 
4398     std::tuple<bool, int> makeTuple();
4399 
4400     void target(bool B) {
4401       auto [BoundFoo, BoundBar] = makeTuple();
4402       bool Baz;
4403       // Include if-then-else to test interaction of `BindingDecl` with join.
4404       if (B) {
4405         Baz = BoundFoo;
4406         (void)BoundBar;
4407         // [[p1]]
4408       } else {
4409         Baz = BoundFoo;
4410       }
4411       (void)0;
4412       // [[p2]]
4413     }
4414   )";
4415   runDataflow(
4416       Code,
4417       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4418          ASTContext &ASTCtx) {
4419         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4420         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4421 
4422         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4423         ASSERT_THAT(BoundFooDecl, NotNull());
4424 
4425         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4426         ASSERT_THAT(BoundBarDecl, NotNull());
4427 
4428         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4429         ASSERT_THAT(BazDecl, NotNull());
4430 
4431         // BindingDecls always map to references -- either lvalue or rvalue, so
4432         // we still need to skip here.
4433         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4434         ASSERT_THAT(BoundFooValue, NotNull());
4435         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4436 
4437         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4438         ASSERT_THAT(BoundBarValue, NotNull());
4439         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4440 
4441         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4442         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4443 
4444         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4445 
4446         // Test that `BoundFooDecl` retains the value we expect, after the join.
4447         BoundFooValue = Env2.getValue(*BoundFooDecl);
4448         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4449       });
4450 }
4451 
4452 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4453   std::string Code = R"(
4454     namespace std {
4455     using size_t = int;
4456     template <class> struct tuple_size;
4457     template <std::size_t, class> struct tuple_element;
4458     template <class...> class tuple;
4459 
4460     namespace {
4461     template <class T, T v>
4462     struct size_helper { static const T value = v; };
4463     } // namespace
4464 
4465     template <class... T>
4466     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4467 
4468     template <std::size_t I, class... T>
4469     struct tuple_element<I, tuple<T...>> {
4470       using type =  __type_pack_element<I, T...>;
4471     };
4472 
4473     template <class...> class tuple {};
4474 
4475     template <std::size_t I, class... T>
4476     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4477     } // namespace std
4478 
4479     std::tuple<bool, int> &getTuple();
4480 
4481     void target(bool B) {
4482       auto &[BoundFoo, BoundBar] = getTuple();
4483       bool Baz;
4484       // Include if-then-else to test interaction of `BindingDecl` with join.
4485       if (B) {
4486         Baz = BoundFoo;
4487         (void)BoundBar;
4488         // [[p1]]
4489       } else {
4490         Baz = BoundFoo;
4491       }
4492       (void)0;
4493       // [[p2]]
4494     }
4495   )";
4496   runDataflow(
4497       Code,
4498       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4499          ASTContext &ASTCtx) {
4500         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4501         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4502 
4503         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4504         ASSERT_THAT(BoundFooDecl, NotNull());
4505 
4506         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4507         ASSERT_THAT(BoundBarDecl, NotNull());
4508 
4509         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4510         ASSERT_THAT(BazDecl, NotNull());
4511 
4512         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4513         ASSERT_THAT(BoundFooValue, NotNull());
4514         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4515 
4516         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4517         ASSERT_THAT(BoundBarValue, NotNull());
4518         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4519 
4520         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4521         // works as expected. We don't test aliasing properties of the
4522         // reference, because we don't model `std::get` and so have no way to
4523         // equate separate references into the tuple.
4524         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4525 
4526         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4527 
4528         // Test that `BoundFooDecl` retains the value we expect, after the join.
4529         BoundFooValue = Env2.getValue(*BoundFooDecl);
4530         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4531       });
4532 }
4533 
4534 TEST(TransferTest, BinaryOperatorComma) {
4535   std::string Code = R"(
4536     void target(int Foo, int Bar) {
4537       int &Baz = (Foo, Bar);
4538       // [[p]]
4539     }
4540   )";
4541   runDataflow(
4542       Code,
4543       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4544          ASTContext &ASTCtx) {
4545         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4546         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4547 
4548         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4549         ASSERT_THAT(BarDecl, NotNull());
4550 
4551         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4552         ASSERT_THAT(BazDecl, NotNull());
4553 
4554         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4555         ASSERT_THAT(BarLoc, NotNull());
4556 
4557         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4558         EXPECT_EQ(BazLoc, BarLoc);
4559       });
4560 }
4561 
4562 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4563   std::string Code = R"(
4564     void target(bool Foo) {
4565       if (Foo) {
4566         (void)0;
4567         // [[if_then]]
4568       } else {
4569         (void)0;
4570         // [[if_else]]
4571       }
4572     }
4573   )";
4574   runDataflow(
4575       Code,
4576       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4577          ASTContext &ASTCtx) {
4578         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4579         const Environment &ThenEnv =
4580             getEnvironmentAtAnnotation(Results, "if_then");
4581         const Environment &ElseEnv =
4582             getEnvironmentAtAnnotation(Results, "if_else");
4583 
4584         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4585         ASSERT_THAT(FooDecl, NotNull());
4586 
4587         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
4588         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
4589 
4590         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
4591         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
4592       });
4593 }
4594 
4595 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4596   std::string Code = R"(
4597     void target(bool Foo) {
4598       while (Foo) {
4599         (void)0;
4600         // [[loop_body]]
4601       }
4602       (void)0;
4603       // [[after_loop]]
4604     }
4605   )";
4606   runDataflow(
4607       Code,
4608       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4609          ASTContext &ASTCtx) {
4610         ASSERT_THAT(Results.keys(),
4611                     UnorderedElementsAre("loop_body", "after_loop"));
4612         const Environment &LoopBodyEnv =
4613             getEnvironmentAtAnnotation(Results, "loop_body");
4614         const Environment &AfterLoopEnv =
4615             getEnvironmentAtAnnotation(Results, "after_loop");
4616 
4617         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4618         ASSERT_THAT(FooDecl, NotNull());
4619 
4620         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
4621         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4622 
4623         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4624         EXPECT_TRUE(
4625             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4626       });
4627 }
4628 
4629 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4630   std::string Code = R"(
4631     void target(bool Foo) {
4632       bool Bar = true;
4633       do {
4634         (void)0;
4635         // [[loop_body]]
4636         Bar = false;
4637       } while (Foo);
4638       (void)0;
4639       // [[after_loop]]
4640     }
4641   )";
4642   runDataflow(
4643       Code,
4644       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4645          ASTContext &ASTCtx) {
4646         ASSERT_THAT(Results.keys(),
4647                     UnorderedElementsAre("loop_body", "after_loop"));
4648         const Environment &LoopBodyEnv =
4649             getEnvironmentAtAnnotation(Results, "loop_body");
4650         const Environment &AfterLoopEnv =
4651             getEnvironmentAtAnnotation(Results, "after_loop");
4652         auto &A = AfterLoopEnv.arena();
4653 
4654         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4655         ASSERT_THAT(FooDecl, NotNull());
4656 
4657         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4658         ASSERT_THAT(BarDecl, NotNull());
4659 
4660         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4661         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
4662         EXPECT_TRUE(
4663             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4664 
4665         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4666         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
4667         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
4668         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
4669       });
4670 }
4671 
4672 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4673   std::string Code = R"(
4674     void target(bool Foo) {
4675       for (; Foo;) {
4676         (void)0;
4677         // [[loop_body]]
4678       }
4679       (void)0;
4680       // [[after_loop]]
4681     }
4682   )";
4683   runDataflow(
4684       Code,
4685       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4686          ASTContext &ASTCtx) {
4687         ASSERT_THAT(Results.keys(),
4688                     UnorderedElementsAre("loop_body", "after_loop"));
4689         const Environment &LoopBodyEnv =
4690             getEnvironmentAtAnnotation(Results, "loop_body");
4691         const Environment &AfterLoopEnv =
4692             getEnvironmentAtAnnotation(Results, "after_loop");
4693 
4694         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4695         ASSERT_THAT(FooDecl, NotNull());
4696 
4697         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4698         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4699 
4700         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4701         EXPECT_TRUE(
4702             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4703       });
4704 }
4705 
4706 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4707   std::string Code = R"(
4708     void target(bool Foo) {
4709       for (;;) {
4710         (void)0;
4711         // [[loop_body]]
4712       }
4713     }
4714   )";
4715   runDataflow(
4716       Code,
4717       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4718          ASTContext &ASTCtx) {
4719         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4720         const Environment &LoopBodyEnv =
4721             getEnvironmentAtAnnotation(Results, "loop_body");
4722 
4723         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4724         ASSERT_THAT(FooDecl, NotNull());
4725 
4726         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4727         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
4728       });
4729 }
4730 
4731 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4732   std::string Code = R"(
4733     bool GiveBool();
4734     void SetBool(bool &Var) { Var = true; }
4735 
4736     void target() {
4737       bool Foo = GiveBool();
4738       SetBool(Foo);
4739       // [[p]]
4740     }
4741   )";
4742   runDataflow(
4743       Code,
4744       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4745          ASTContext &ASTCtx) {
4746         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4747         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4748 
4749         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4750         ASSERT_THAT(FooDecl, NotNull());
4751 
4752         auto &FooVal = getFormula(*FooDecl, Env);
4753         EXPECT_FALSE(Env.proves(FooVal));
4754         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
4755       },
4756       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4757 }
4758 
4759 TEST(TransferTest, ContextSensitiveReturnReference) {
4760   std::string Code = R"(
4761     class S {};
4762     S& target(bool b, S &s) {
4763       return s;
4764       // [[p]]
4765     }
4766   )";
4767   runDataflow(
4768       Code,
4769       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4770          ASTContext &ASTCtx) {
4771         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4772 
4773         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4774         ASSERT_THAT(SDecl, NotNull());
4775 
4776         auto *SLoc = Env.getStorageLocation(*SDecl);
4777         ASSERT_THAT(SLoc, NotNull());
4778 
4779         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4780       },
4781       {BuiltinOptions{ContextSensitiveOptions{}}});
4782 }
4783 
4784 // This test is a regression test, based on a real crash.
4785 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4786   std::string Code = R"(
4787     class S {};
4788     S& target(bool b, S &s) {
4789       return b ? s : s;
4790       // [[p]]
4791     }
4792   )";
4793   runDataflow(
4794       Code,
4795       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4796          ASTContext &ASTCtx) {
4797         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4798         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4799 
4800         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4801         ASSERT_THAT(SDecl, NotNull());
4802 
4803         auto *SLoc = Env.getStorageLocation(*SDecl);
4804         ASSERT_THAT(SLoc, NotNull());
4805         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4806 
4807         auto *Loc = Env.getReturnStorageLocation();
4808         ASSERT_THAT(Loc, NotNull());
4809         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4810 
4811         // TODO: We would really like to make this stronger assertion, but that
4812         // doesn't work because we don't propagate values correctly through
4813         // the conditional operator yet.
4814         // ASSERT_THAT(Loc, Eq(SLoc));
4815       },
4816       {BuiltinOptions{ContextSensitiveOptions{}}});
4817 }
4818 
4819 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4820   std::string Code = R"(
4821     class S {};
4822     S &callee(bool b, S &s1_parm, S &s2_parm) {
4823       if (b)
4824         return s1_parm;
4825       else
4826         return s2_parm;
4827     }
4828     void target(bool b) {
4829       S s1;
4830       S s2;
4831       S &return_s1 = s1;
4832       S &return_s2 = s2;
4833       S &return_dont_know = callee(b, s1, s2);
4834       // [[p]]
4835     }
4836   )";
4837   runDataflow(
4838       Code,
4839       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4840          ASTContext &ASTCtx) {
4841         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4842 
4843         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4844         ASSERT_THAT(S1, NotNull());
4845         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4846         ASSERT_THAT(S2, NotNull());
4847         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4848         ASSERT_THAT(ReturnS1, NotNull());
4849         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4850         ASSERT_THAT(ReturnS2, NotNull());
4851         const ValueDecl *ReturnDontKnow =
4852             findValueDecl(ASTCtx, "return_dont_know");
4853         ASSERT_THAT(ReturnDontKnow, NotNull());
4854 
4855         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4856         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4857 
4858         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4859         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4860 
4861         // In the case where we don't have a consistent storage location for
4862         // the return value, the framework creates a new storage location, which
4863         // should be different from the storage locations of `s1` and `s2`.
4864         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4865         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4866       },
4867       {BuiltinOptions{ContextSensitiveOptions{}}});
4868 }
4869 
4870 TEST(TransferTest, ContextSensitiveDepthZero) {
4871   std::string Code = R"(
4872     bool GiveBool();
4873     void SetBool(bool &Var) { Var = true; }
4874 
4875     void target() {
4876       bool Foo = GiveBool();
4877       SetBool(Foo);
4878       // [[p]]
4879     }
4880   )";
4881   runDataflow(
4882       Code,
4883       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4884          ASTContext &ASTCtx) {
4885         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4886         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4887 
4888         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4889         ASSERT_THAT(FooDecl, NotNull());
4890 
4891         auto &FooVal = getFormula(*FooDecl, Env);
4892         EXPECT_FALSE(Env.proves(FooVal));
4893         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
4894       },
4895       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4896 }
4897 
4898 TEST(TransferTest, ContextSensitiveSetTrue) {
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_TRUE(Env.proves(FooVal));
4921       },
4922       {BuiltinOptions{ContextSensitiveOptions{}}});
4923 }
4924 
4925 TEST(TransferTest, ContextSensitiveSetFalse) {
4926   std::string Code = R"(
4927     bool GiveBool();
4928     void SetBool(bool &Var) { Var = false; }
4929 
4930     void target() {
4931       bool Foo = GiveBool();
4932       SetBool(Foo);
4933       // [[p]]
4934     }
4935   )";
4936   runDataflow(
4937       Code,
4938       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4939          ASTContext &ASTCtx) {
4940         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4941         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4942 
4943         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4944         ASSERT_THAT(FooDecl, NotNull());
4945 
4946         auto &FooVal = getFormula(*FooDecl, Env);
4947         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
4948       },
4949       {BuiltinOptions{ContextSensitiveOptions{}}});
4950 }
4951 
4952 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4953   std::string Code = R"(
4954     bool GiveBool();
4955     void SetBool(bool &Var, bool Val) { Var = Val; }
4956 
4957     void target() {
4958       bool Foo = GiveBool();
4959       bool Bar = GiveBool();
4960       SetBool(Foo, true);
4961       SetBool(Bar, false);
4962       // [[p]]
4963     }
4964   )";
4965   runDataflow(
4966       Code,
4967       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4968          ASTContext &ASTCtx) {
4969         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4970         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4971         auto &A = Env.arena();
4972 
4973         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4974         ASSERT_THAT(FooDecl, NotNull());
4975 
4976         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4977         ASSERT_THAT(BarDecl, NotNull());
4978 
4979         auto &FooVal = getFormula(*FooDecl, Env);
4980         EXPECT_TRUE(Env.proves(FooVal));
4981         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
4982 
4983         auto &BarVal = getFormula(*BarDecl, Env);
4984         EXPECT_FALSE(Env.proves(BarVal));
4985         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
4986       },
4987       {BuiltinOptions{ContextSensitiveOptions{}}});
4988 }
4989 
4990 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4991   std::string Code = R"(
4992     bool GiveBool();
4993     void SetBool1(bool &Var) { Var = true; }
4994     void SetBool2(bool &Var) { SetBool1(Var); }
4995 
4996     void target() {
4997       bool Foo = GiveBool();
4998       SetBool2(Foo);
4999       // [[p]]
5000     }
5001   )";
5002   runDataflow(
5003       Code,
5004       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5005          ASTContext &ASTCtx) {
5006         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5007         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5008 
5009         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5010         ASSERT_THAT(FooDecl, NotNull());
5011 
5012         auto &FooVal = getFormula(*FooDecl, Env);
5013         EXPECT_FALSE(Env.proves(FooVal));
5014         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5015       },
5016       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5017 }
5018 
5019 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5020   std::string Code = R"(
5021     bool GiveBool();
5022     void SetBool1(bool &Var) { Var = true; }
5023     void SetBool2(bool &Var) { SetBool1(Var); }
5024 
5025     void target() {
5026       bool Foo = GiveBool();
5027       SetBool2(Foo);
5028       // [[p]]
5029     }
5030   )";
5031   runDataflow(
5032       Code,
5033       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5034          ASTContext &ASTCtx) {
5035         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5036         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5037 
5038         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5039         ASSERT_THAT(FooDecl, NotNull());
5040 
5041         auto &FooVal = getFormula(*FooDecl, Env);
5042         EXPECT_TRUE(Env.proves(FooVal));
5043       },
5044       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5045 }
5046 
5047 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5048   std::string Code = R"(
5049     bool GiveBool();
5050     void SetBool1(bool &Var) { Var = true; }
5051     void SetBool2(bool &Var) { SetBool1(Var); }
5052     void SetBool3(bool &Var) { SetBool2(Var); }
5053 
5054     void target() {
5055       bool Foo = GiveBool();
5056       SetBool3(Foo);
5057       // [[p]]
5058     }
5059   )";
5060   runDataflow(
5061       Code,
5062       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5063          ASTContext &ASTCtx) {
5064         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5065         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5066 
5067         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5068         ASSERT_THAT(FooDecl, NotNull());
5069 
5070         auto &FooVal = getFormula(*FooDecl, Env);
5071         EXPECT_FALSE(Env.proves(FooVal));
5072         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5073       },
5074       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5075 }
5076 
5077 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5078   std::string Code = R"(
5079     bool GiveBool();
5080     void SetBool1(bool &Var) { Var = true; }
5081     void SetBool2(bool &Var) { SetBool1(Var); }
5082     void SetBool3(bool &Var) { SetBool2(Var); }
5083 
5084     void target() {
5085       bool Foo = GiveBool();
5086       SetBool3(Foo);
5087       // [[p]]
5088     }
5089   )";
5090   runDataflow(
5091       Code,
5092       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5093          ASTContext &ASTCtx) {
5094         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5095         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5096 
5097         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5098         ASSERT_THAT(FooDecl, NotNull());
5099 
5100         auto &FooVal = getFormula(*FooDecl, Env);
5101         EXPECT_TRUE(Env.proves(FooVal));
5102       },
5103       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5104 }
5105 
5106 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5107   std::string Code = R"(
5108     bool Pong(bool X, bool Y);
5109 
5110     bool Ping(bool X, bool Y) {
5111       if (X) {
5112         return Y;
5113       } else {
5114         return Pong(!X, Y);
5115       }
5116     }
5117 
5118     bool Pong(bool X, bool Y) {
5119       if (Y) {
5120         return X;
5121       } else {
5122         return Ping(X, !Y);
5123       }
5124     }
5125 
5126     void target() {
5127       bool Foo = Ping(false, false);
5128       // [[p]]
5129     }
5130   )";
5131   runDataflow(
5132       Code,
5133       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5134          ASTContext &ASTCtx) {
5135         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5136         // The analysis doesn't crash...
5137         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5138 
5139         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5140         ASSERT_THAT(FooDecl, NotNull());
5141 
5142         auto &FooVal = getFormula(*FooDecl, Env);
5143         // ... but it also can't prove anything here.
5144         EXPECT_FALSE(Env.proves(FooVal));
5145         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5146       },
5147       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5148 }
5149 
5150 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5151   std::string Code = R"(
5152     void SetBools(bool &Var1, bool &Var2) {
5153       Var1 = true;
5154       Var2 = false;
5155     }
5156 
5157     void target() {
5158       bool Foo = false;
5159       bool Bar = true;
5160       SetBools(Foo, Bar);
5161       // [[p]]
5162     }
5163   )";
5164   runDataflow(
5165       Code,
5166       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5167          ASTContext &ASTCtx) {
5168         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5169         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5170 
5171         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5172         ASSERT_THAT(FooDecl, NotNull());
5173 
5174         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5175         ASSERT_THAT(BarDecl, NotNull());
5176 
5177         auto &FooVal = getFormula(*FooDecl, Env);
5178         EXPECT_TRUE(Env.proves(FooVal));
5179         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5180 
5181         auto &BarVal = getFormula(*BarDecl, Env);
5182         EXPECT_FALSE(Env.proves(BarVal));
5183         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5184       },
5185       {BuiltinOptions{ContextSensitiveOptions{}}});
5186 }
5187 
5188 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5189   std::string Code = R"(
5190     void IfCond(bool Cond, bool &Then, bool &Else) {
5191       if (Cond) {
5192         Then = true;
5193       } else {
5194         Else = true;
5195       }
5196     }
5197 
5198     void target() {
5199       bool Foo = false;
5200       bool Bar = false;
5201       bool Baz = false;
5202       IfCond(Foo, Bar, Baz);
5203       // [[p]]
5204     }
5205   )";
5206   runDataflow(
5207       Code,
5208       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5209          ASTContext &ASTCtx) {
5210         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5211         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5212 
5213         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5214         ASSERT_THAT(BarDecl, NotNull());
5215 
5216         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5217         ASSERT_THAT(BazDecl, NotNull());
5218 
5219         auto &BarVal = getFormula(*BarDecl, Env);
5220         EXPECT_FALSE(Env.proves(BarVal));
5221         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5222 
5223         auto &BazVal = getFormula(*BazDecl, Env);
5224         EXPECT_TRUE(Env.proves(BazVal));
5225         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5226       },
5227       {BuiltinOptions{ContextSensitiveOptions{}}});
5228 }
5229 
5230 TEST(TransferTest, ContextSensitiveReturnVoid) {
5231   std::string Code = R"(
5232     void Noop() { return; }
5233 
5234     void target() {
5235       Noop();
5236       // [[p]]
5237     }
5238   )";
5239   runDataflow(
5240       Code,
5241       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5242          ASTContext &ASTCtx) {
5243         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5244         // This just tests that the analysis doesn't crash.
5245       },
5246       {BuiltinOptions{ContextSensitiveOptions{}}});
5247 }
5248 
5249 TEST(TransferTest, ContextSensitiveReturnTrue) {
5250   std::string Code = R"(
5251     bool GiveBool() { return true; }
5252 
5253     void target() {
5254       bool Foo = GiveBool();
5255       // [[p]]
5256     }
5257   )";
5258   runDataflow(
5259       Code,
5260       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5261          ASTContext &ASTCtx) {
5262         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5263         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5264 
5265         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5266         ASSERT_THAT(FooDecl, NotNull());
5267 
5268         auto &FooVal = getFormula(*FooDecl, Env);
5269         EXPECT_TRUE(Env.proves(FooVal));
5270       },
5271       {BuiltinOptions{ContextSensitiveOptions{}}});
5272 }
5273 
5274 TEST(TransferTest, ContextSensitiveReturnFalse) {
5275   std::string Code = R"(
5276     bool GiveBool() { return false; }
5277 
5278     void target() {
5279       bool Foo = GiveBool();
5280       // [[p]]
5281     }
5282   )";
5283   runDataflow(
5284       Code,
5285       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5286          ASTContext &ASTCtx) {
5287         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5288         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5289 
5290         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5291         ASSERT_THAT(FooDecl, NotNull());
5292 
5293         auto &FooVal = getFormula(*FooDecl, Env);
5294         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5295       },
5296       {BuiltinOptions{ContextSensitiveOptions{}}});
5297 }
5298 
5299 TEST(TransferTest, ContextSensitiveReturnArg) {
5300   std::string Code = R"(
5301     bool GiveBool();
5302     bool GiveBack(bool Arg) { return Arg; }
5303 
5304     void target() {
5305       bool Foo = GiveBool();
5306       bool Bar = GiveBack(Foo);
5307       bool Baz = Foo == Bar;
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 *BazDecl = findValueDecl(ASTCtx, "Baz");
5319         ASSERT_THAT(BazDecl, NotNull());
5320 
5321         auto &BazVal = getFormula(*BazDecl, Env);
5322         EXPECT_TRUE(Env.proves(BazVal));
5323       },
5324       {BuiltinOptions{ContextSensitiveOptions{}}});
5325 }
5326 
5327 TEST(TransferTest, ContextSensitiveReturnInt) {
5328   std::string Code = R"(
5329     int identity(int x) { return x; }
5330 
5331     void target() {
5332       int y = identity(42);
5333       // [[p]]
5334     }
5335   )";
5336   runDataflow(
5337       Code,
5338       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5339          ASTContext &ASTCtx) {
5340         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5341         // This just tests that the analysis doesn't crash.
5342       },
5343       {BuiltinOptions{ContextSensitiveOptions{}}});
5344 }
5345 
5346 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5347   std::string Code = R"(
5348     class MyClass {
5349     public:
5350       bool giveBool() { return true; }
5351     };
5352 
5353     void target() {
5354       MyClass MyObj;
5355       bool Foo = MyObj.giveBool();
5356       // [[p]]
5357     }
5358   )";
5359   runDataflow(
5360       Code,
5361       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5362          ASTContext &ASTCtx) {
5363         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5364         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5365 
5366         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5367         ASSERT_THAT(FooDecl, NotNull());
5368 
5369         auto &FooVal = getFormula(*FooDecl, Env);
5370         EXPECT_TRUE(Env.proves(FooVal));
5371       },
5372       {BuiltinOptions{ContextSensitiveOptions{}}});
5373 }
5374 
5375 TEST(TransferTest, ContextSensitiveMethodGetter) {
5376   std::string Code = R"(
5377     class MyClass {
5378     public:
5379       bool getField() { return Field; }
5380 
5381       bool Field;
5382     };
5383 
5384     void target() {
5385       MyClass MyObj;
5386       MyObj.Field = true;
5387       bool Foo = MyObj.getField();
5388       // [[p]]
5389     }
5390   )";
5391   runDataflow(
5392       Code,
5393       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5394          ASTContext &ASTCtx) {
5395         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5396         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5397 
5398         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5399         ASSERT_THAT(FooDecl, NotNull());
5400 
5401         auto &FooVal = getFormula(*FooDecl, Env);
5402         EXPECT_TRUE(Env.proves(FooVal));
5403       },
5404       {BuiltinOptions{ContextSensitiveOptions{}}});
5405 }
5406 
5407 TEST(TransferTest, ContextSensitiveMethodSetter) {
5408   std::string Code = R"(
5409     class MyClass {
5410     public:
5411       void setField(bool Val) { Field = Val; }
5412 
5413       bool Field;
5414     };
5415 
5416     void target() {
5417       MyClass MyObj;
5418       MyObj.setField(true);
5419       bool Foo = MyObj.Field;
5420       // [[p]]
5421     }
5422   )";
5423   runDataflow(
5424       Code,
5425       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5426          ASTContext &ASTCtx) {
5427         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5428         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5429 
5430         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5431         ASSERT_THAT(FooDecl, NotNull());
5432 
5433         auto &FooVal = getFormula(*FooDecl, Env);
5434         EXPECT_TRUE(Env.proves(FooVal));
5435       },
5436       {BuiltinOptions{ContextSensitiveOptions{}}});
5437 }
5438 
5439 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5440   std::string Code = R"(
5441     class MyClass {
5442     public:
5443       bool getField() { return Field; }
5444       void setField(bool Val) { Field = Val; }
5445 
5446     private:
5447       bool Field;
5448     };
5449 
5450     void target() {
5451       MyClass MyObj;
5452       MyObj.setField(true);
5453       bool Foo = MyObj.getField();
5454       // [[p]]
5455     }
5456   )";
5457   runDataflow(
5458       Code,
5459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5460          ASTContext &ASTCtx) {
5461         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5462         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5463 
5464         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5465         ASSERT_THAT(FooDecl, NotNull());
5466 
5467         auto &FooVal = getFormula(*FooDecl, Env);
5468         EXPECT_TRUE(Env.proves(FooVal));
5469       },
5470       {BuiltinOptions{ContextSensitiveOptions{}}});
5471 }
5472 
5473 
5474 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5475   std::string Code = R"(
5476     class MyClass {
5477     public:
5478       void Inner() { MyField = true; }
5479       void Outer() { Inner(); }
5480 
5481       bool MyField;
5482     };
5483 
5484     void target() {
5485       MyClass MyObj;
5486       MyObj.Outer();
5487       bool Foo = MyObj.MyField;
5488       // [[p]]
5489     }
5490   )";
5491   runDataflow(
5492       Code,
5493       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5494          ASTContext &ASTCtx) {
5495         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5496         ;
5497         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5498 
5499         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5500         ASSERT_THAT(FooDecl, NotNull());
5501 
5502         auto &FooVal = getFormula(*FooDecl, Env);
5503         EXPECT_TRUE(Env.proves(FooVal));
5504       },
5505       {BuiltinOptions{ContextSensitiveOptions{}}});
5506 }
5507 
5508 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5509   std::string Code = R"(
5510     class MyClass {
5511     public:
5512       bool Inner() { return MyField; }
5513       bool Outer() { return Inner(); }
5514 
5515       bool MyField;
5516     };
5517 
5518     void target() {
5519       MyClass MyObj;
5520       MyObj.MyField = true;
5521       bool Foo = MyObj.Outer();
5522       // [[p]]
5523     }
5524   )";
5525   runDataflow(
5526       Code,
5527       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5528          ASTContext &ASTCtx) {
5529         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5530         ;
5531         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5532 
5533         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5534         ASSERT_THAT(FooDecl, NotNull());
5535 
5536         auto &FooVal = getFormula(*FooDecl, Env);
5537         EXPECT_TRUE(Env.proves(FooVal));
5538       },
5539       {BuiltinOptions{ContextSensitiveOptions{}}});
5540 }
5541 
5542 TEST(TransferTest, ContextSensitiveConstructorBody) {
5543   std::string Code = R"(
5544     class MyClass {
5545     public:
5546       MyClass() { MyField = true; }
5547 
5548       bool MyField;
5549     };
5550 
5551     void target() {
5552       MyClass MyObj;
5553       bool Foo = MyObj.MyField;
5554       // [[p]]
5555     }
5556   )";
5557   runDataflow(
5558       Code,
5559       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5560          ASTContext &ASTCtx) {
5561         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5562         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5563 
5564         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5565         ASSERT_THAT(FooDecl, NotNull());
5566 
5567         auto &FooVal = getFormula(*FooDecl, Env);
5568         EXPECT_TRUE(Env.proves(FooVal));
5569       },
5570       {BuiltinOptions{ContextSensitiveOptions{}}});
5571 }
5572 
5573 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5574   std::string Code = R"(
5575     class MyClass {
5576     public:
5577       MyClass() : MyField(true) {}
5578 
5579       bool MyField;
5580     };
5581 
5582     void target() {
5583       MyClass MyObj;
5584       bool Foo = MyObj.MyField;
5585       // [[p]]
5586     }
5587   )";
5588   runDataflow(
5589       Code,
5590       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5591          ASTContext &ASTCtx) {
5592         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5593         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5594 
5595         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5596         ASSERT_THAT(FooDecl, NotNull());
5597 
5598         auto &FooVal = getFormula(*FooDecl, Env);
5599         EXPECT_TRUE(Env.proves(FooVal));
5600       },
5601       {BuiltinOptions{ContextSensitiveOptions{}}});
5602 }
5603 
5604 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5605   std::string Code = R"(
5606     class MyClass {
5607     public:
5608       MyClass() = default;
5609 
5610       bool MyField = true;
5611     };
5612 
5613     void target() {
5614       MyClass MyObj;
5615       bool Foo = MyObj.MyField;
5616       // [[p]]
5617     }
5618   )";
5619   runDataflow(
5620       Code,
5621       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5622          ASTContext &ASTCtx) {
5623         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5624         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5625 
5626         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5627         ASSERT_THAT(FooDecl, NotNull());
5628 
5629         auto &FooVal = getFormula(*FooDecl, Env);
5630         EXPECT_TRUE(Env.proves(FooVal));
5631       },
5632       {BuiltinOptions{ContextSensitiveOptions{}}});
5633 }
5634 
5635 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
5636   // Test that the `this` pointer seen in the constructor has the same value
5637   // as the address of the variable the object is constructed into.
5638   std::string Code = R"(
5639     class MyClass {
5640     public:
5641       MyClass() : Self(this) {}
5642       MyClass *Self;
5643     };
5644 
5645     void target() {
5646       MyClass MyObj;
5647       MyClass *SelfPtr = MyObj.Self;
5648       // [[p]]
5649     }
5650   )";
5651   runDataflow(
5652       Code,
5653       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5654          ASTContext &ASTCtx) {
5655         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5656 
5657         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
5658         ASSERT_THAT(MyObjDecl, NotNull());
5659 
5660         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
5661         ASSERT_THAT(SelfDecl, NotNull());
5662 
5663         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5664         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
5665         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
5666       },
5667       {BuiltinOptions{ContextSensitiveOptions{}}});
5668 }
5669 
5670 TEST(TransferTest, UnnamedBitfieldInitializer) {
5671   std::string Code = R"(
5672     struct B {};
5673     struct A {
5674       unsigned a;
5675       unsigned : 4;
5676       unsigned c;
5677       B b;
5678     };
5679     void target() {
5680       A a = {};
5681       A test = a;
5682       (void)test.c;
5683     }
5684   )";
5685   runDataflow(
5686       Code,
5687       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5688          ASTContext &ASTCtx) {
5689         // This doesn't need a body because this test was crashing the framework
5690         // before handling correctly Unnamed bitfields in `InitListExpr`.
5691       });
5692 }
5693 
5694 // Repro for a crash that used to occur with chained short-circuiting logical
5695 // operators.
5696 TEST(TransferTest, ChainedLogicalOps) {
5697   std::string Code = R"(
5698     bool target() {
5699       bool b = true || false || false || false;
5700       // [[p]]
5701       return b;
5702     }
5703   )";
5704   runDataflow(
5705       Code,
5706       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5707          ASTContext &ASTCtx) {
5708         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5709         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
5710         EXPECT_TRUE(Env.proves(B));
5711       });
5712 }
5713 
5714 // Repro for a crash that used to occur when we call a `noreturn` function
5715 // within one of the operands of a `&&` or `||` operator.
5716 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5717   std::string Code = R"(
5718     __attribute__((noreturn)) int doesnt_return();
5719     bool some_condition();
5720     void target(bool b1, bool b2) {
5721       // Neither of these should crash. In addition, if we don't terminate the
5722       // program, we know that the operators need to trigger the short-circuit
5723       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5724       // will be true.
5725       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5726       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5727 
5728       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5729       // entire expression unreachable. So we know that in both of the following
5730       // cases, if `target()` terminates, the `else` branch was taken.
5731       bool NoreturnOnLhsMakesAndUnreachable = false;
5732       if (some_condition())
5733          doesnt_return() > 0 && some_condition();
5734       else
5735          NoreturnOnLhsMakesAndUnreachable = true;
5736 
5737       bool NoreturnOnLhsMakesOrUnreachable = false;
5738       if (some_condition())
5739          doesnt_return() > 0 || some_condition();
5740       else
5741          NoreturnOnLhsMakesOrUnreachable = true;
5742 
5743       // [[p]]
5744     }
5745   )";
5746   runDataflow(
5747       Code,
5748       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5749          ASTContext &ASTCtx) {
5750         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5751         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5752         auto &A = Env.arena();
5753 
5754         // Check that [[p]] is reachable with a non-false flow condition.
5755         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
5756 
5757         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
5758         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
5759 
5760         auto &NoreturnOnRhsOfAnd =
5761             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
5762         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
5763 
5764         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
5765         EXPECT_TRUE(Env.proves(B2));
5766 
5767         auto &NoreturnOnRhsOfOr =
5768             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
5769                 .formula();
5770         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
5771 
5772         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5773             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
5774         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
5775 
5776         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5777             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
5778         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
5779       });
5780 }
5781 
5782 TEST(TransferTest, NewExpressions) {
5783   std::string Code = R"(
5784     void target() {
5785       int *p = new int(42);
5786       // [[after_new]]
5787     }
5788   )";
5789   runDataflow(
5790       Code,
5791       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5792          ASTContext &ASTCtx) {
5793         const Environment &Env =
5794             getEnvironmentAtAnnotation(Results, "after_new");
5795 
5796         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5797 
5798         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5799       });
5800 }
5801 
5802 TEST(TransferTest, NewExpressions_Structs) {
5803   std::string Code = R"(
5804     struct Inner {
5805       int InnerField;
5806     };
5807 
5808     struct Outer {
5809       Inner OuterField;
5810     };
5811 
5812     void target() {
5813       Outer *p = new Outer;
5814       // Access the fields to make sure the analysis actually generates children
5815       // for them in the `RecordStorageLocation` and `RecordValue`.
5816       p->OuterField.InnerField;
5817       // [[after_new]]
5818     }
5819   )";
5820   runDataflow(
5821       Code,
5822       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5823          ASTContext &ASTCtx) {
5824         const Environment &Env =
5825             getEnvironmentAtAnnotation(Results, "after_new");
5826 
5827         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5828         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5829 
5830         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5831 
5832         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
5833         auto &OuterFieldLoc =
5834             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
5835         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
5836 
5837         // Values for the struct and all fields exist after the new.
5838         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5839         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5840         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5841       });
5842 }
5843 
5844 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5845   std::string Code = R"(
5846     struct A { static void static_member_func(); };
5847     void target() {
5848       // To check that we're treating function-to-pointer decay correctly,
5849       // create two pointers, then verify they refer to the same storage
5850       // location.
5851       // We need to do the test this way because even if an initializer (in this
5852       // case, the function-to-pointer decay) does not create a value, we still
5853       // create a value for the variable.
5854       void (*non_member_p1)() = target;
5855       void (*non_member_p2)() = target;
5856 
5857       // Do the same thing but for a static member function.
5858       void (*member_p1)() = A::static_member_func;
5859       void (*member_p2)() = A::static_member_func;
5860       // [[p]]
5861     }
5862   )";
5863   runDataflow(
5864       Code,
5865       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5866          ASTContext &ASTCtx) {
5867         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5868 
5869         auto &NonMemberP1 =
5870             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
5871         auto &NonMemberP2 =
5872             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
5873         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
5874 
5875         auto &MemberP1 =
5876             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
5877         auto &MemberP2 =
5878             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
5879         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
5880       });
5881 }
5882 
5883 // Check that a builtin function is not associated with a value. (It's only
5884 // possible to call builtin functions directly, not take their address.)
5885 TEST(TransferTest, BuiltinFunctionModeled) {
5886   std::string Code = R"(
5887     void target() {
5888       __builtin_expect(0, 0);
5889       // [[p]]
5890     }
5891   )";
5892   runDataflow(
5893       Code,
5894       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5895          ASTContext &ASTCtx) {
5896         using ast_matchers::selectFirst;
5897         using ast_matchers::match;
5898         using ast_matchers::traverse;
5899         using ast_matchers::implicitCastExpr;
5900         using ast_matchers::hasCastKind;
5901 
5902         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5903 
5904         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
5905             "implicit_cast",
5906             match(traverse(TK_AsIs,
5907                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
5908                                .bind("implicit_cast")),
5909                   ASTCtx));
5910 
5911         ASSERT_THAT(ImplicitCast, NotNull());
5912         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
5913       });
5914 }
5915 
5916 // Check that a callee of a member operator call is modeled as a `PointerValue`.
5917 // Member operator calls are unusual in that their callee is a pointer that
5918 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
5919 // member functions, the callee is a `MemberExpr` (which does not have pointer
5920 // type).
5921 // We want to make sure that we produce a pointer value for the callee in this
5922 // specific scenario and that its storage location is durable (for convergence).
5923 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
5924   std::string Code = R"(
5925     struct S {
5926       bool operator!=(S s);
5927     };
5928     void target() {
5929       S s;
5930       (void)(s != s);
5931       (void)(s != s);
5932       // [[p]]
5933     }
5934   )";
5935   runDataflow(
5936       Code,
5937       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5938          ASTContext &ASTCtx) {
5939         using ast_matchers::selectFirst;
5940         using ast_matchers::match;
5941         using ast_matchers::traverse;
5942         using ast_matchers::cxxOperatorCallExpr;
5943 
5944         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5945 
5946         auto Matches = match(
5947             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
5948 
5949         ASSERT_EQ(Matches.size(), 2UL);
5950 
5951         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
5952         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
5953 
5954         ASSERT_THAT(Call1, NotNull());
5955         ASSERT_THAT(Call2, NotNull());
5956 
5957         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
5958                   CK_FunctionToPointerDecay);
5959         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
5960                   CK_FunctionToPointerDecay);
5961 
5962         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
5963         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
5964 
5965         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
5966       });
5967 }
5968 
5969 // Check that fields of anonymous records are modeled.
5970 TEST(TransferTest, AnonymousStruct) {
5971   std::string Code = R"(
5972     struct S {
5973       struct {
5974         bool b;
5975       };
5976     };
5977     void target() {
5978       S s;
5979       s.b = true;
5980       // [[p]]
5981     }
5982   )";
5983   runDataflow(
5984       Code,
5985       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5986          ASTContext &ASTCtx) {
5987         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5988         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5989         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5990         const IndirectFieldDecl *IndirectField =
5991             findIndirectFieldDecl(ASTCtx, "b");
5992 
5993         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
5994         auto &AnonStruct = *cast<RecordStorageLocation>(
5995             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
5996 
5997         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5998         ASSERT_TRUE(Env.proves(B->formula()));
5999       });
6000 }
6001 
6002 TEST(TransferTest, AnonymousStructWithInitializer) {
6003   std::string Code = R"(
6004     struct target {
6005       target() {
6006         (void)0;
6007         // [[p]]
6008       }
6009       struct {
6010         bool b = true;
6011       };
6012     };
6013   )";
6014   runDataflow(
6015       Code,
6016       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6017          ASTContext &ASTCtx) {
6018         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6019         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6020         const IndirectFieldDecl *IndirectField =
6021             findIndirectFieldDecl(ASTCtx, "b");
6022 
6023         auto *ThisLoc =
6024             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6025         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6026             *cast<ValueDecl>(IndirectField->chain().front())));
6027 
6028         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6029         ASSERT_TRUE(Env.proves(B->formula()));
6030       });
6031 }
6032 
6033 TEST(TransferTest, AnonymousStructWithReferenceField) {
6034   std::string Code = R"(
6035     int global_i = 0;
6036     struct target {
6037       target() {
6038         (void)0;
6039         // [[p]]
6040       }
6041       struct {
6042         int &i = global_i;
6043       };
6044     };
6045   )";
6046   runDataflow(
6047       Code,
6048       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6049          ASTContext &ASTCtx) {
6050         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6051         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6052         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6053         const IndirectFieldDecl *IndirectField =
6054             findIndirectFieldDecl(ASTCtx, "i");
6055 
6056         auto *ThisLoc =
6057             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6058         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6059             *cast<ValueDecl>(IndirectField->chain().front())));
6060 
6061         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6062                   Env.getStorageLocation(*GlobalIDecl));
6063       });
6064 }
6065 
6066 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6067   // This is a crash repro.
6068   // `false` block may not have been processed when we try to evaluate the `||`
6069   // after visiting `true`, because it is not necessary (and therefore the edge
6070   // is marked unreachable). Trying to get the analysis state via
6071   // `getEnvironment` for the subexpression still should not crash.
6072   std::string Code = R"(
6073     int target(int i) {
6074       if ((i < 0 && true) || false) {
6075         return 0;
6076       }
6077       return 0;
6078     }
6079   )";
6080   runDataflow(
6081       Code,
6082       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6083          ASTContext &ASTCtx) {});
6084 }
6085 
6086 TEST(TransferTest, LambdaCaptureByCopy) {
6087   std::string Code = R"(
6088     void target(int Foo, int Bar) {
6089       [Foo]() {
6090         (void)0;
6091         // [[p]]
6092       }();
6093     }
6094   )";
6095   runDataflowOnLambda(
6096       Code,
6097       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6098          ASTContext &ASTCtx) {
6099         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6100         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6101 
6102         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6103         ASSERT_THAT(FooDecl, NotNull());
6104 
6105         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6106         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6107 
6108         const Value *FooVal = Env.getValue(*FooLoc);
6109         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6110 
6111         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6112         ASSERT_THAT(BarDecl, NotNull());
6113 
6114         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6115         EXPECT_THAT(BarLoc, IsNull());
6116       });
6117 }
6118 
6119 TEST(TransferTest, LambdaCaptureByReference) {
6120   std::string Code = R"(
6121     void target(int Foo, int Bar) {
6122       [&Foo]() {
6123         (void)0;
6124         // [[p]]
6125       }();
6126     }
6127   )";
6128   runDataflowOnLambda(
6129       Code,
6130       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6131          ASTContext &ASTCtx) {
6132         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6133         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6134 
6135         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6136         ASSERT_THAT(FooDecl, NotNull());
6137 
6138         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6139         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6140 
6141         const Value *FooVal = Env.getValue(*FooLoc);
6142         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6143 
6144         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6145         ASSERT_THAT(BarDecl, NotNull());
6146 
6147         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6148         EXPECT_THAT(BarLoc, IsNull());
6149       });
6150 }
6151 
6152 TEST(TransferTest, LambdaCaptureWithInitializer) {
6153   std::string Code = R"(
6154     void target(int Bar) {
6155       [Foo=Bar]() {
6156         (void)0;
6157         // [[p]]
6158       }();
6159     }
6160   )";
6161   runDataflowOnLambda(
6162       Code,
6163       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6164          ASTContext &ASTCtx) {
6165         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6166         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6167 
6168         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6169         ASSERT_THAT(FooDecl, NotNull());
6170 
6171         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6172         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6173 
6174         const Value *FooVal = Env.getValue(*FooLoc);
6175         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6176 
6177         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6178         ASSERT_THAT(BarDecl, NotNull());
6179 
6180         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6181         EXPECT_THAT(BarLoc, IsNull());
6182       });
6183 }
6184 
6185 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
6186   std::string Code = R"(
6187     void target(int Foo, int Bar) {
6188       [=]() {
6189         Foo;
6190         // [[p]]
6191       }();
6192     }
6193   )";
6194   runDataflowOnLambda(
6195       Code,
6196       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6197          ASTContext &ASTCtx) {
6198         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6199         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6200 
6201         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6202         ASSERT_THAT(FooDecl, NotNull());
6203 
6204         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6205         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6206 
6207         const Value *FooVal = Env.getValue(*FooLoc);
6208         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6209 
6210         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6211         ASSERT_THAT(BarDecl, NotNull());
6212 
6213         // There is no storage location for `Bar` because it isn't used in the
6214         // body of the lambda.
6215         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6216         EXPECT_THAT(BarLoc, IsNull());
6217       });
6218 }
6219 
6220 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
6221   std::string Code = R"(
6222     void target(int Foo, int Bar) {
6223       [&]() {
6224         Foo;
6225         // [[p]]
6226       }();
6227     }
6228   )";
6229   runDataflowOnLambda(
6230       Code,
6231       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6232          ASTContext &ASTCtx) {
6233         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6234         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6235 
6236         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6237         ASSERT_THAT(FooDecl, NotNull());
6238 
6239         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6240         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6241 
6242         const Value *FooVal = Env.getValue(*FooLoc);
6243         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6244 
6245         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6246         ASSERT_THAT(BarDecl, NotNull());
6247 
6248         // There is no storage location for `Bar` because it isn't used in the
6249         // body of the lambda.
6250         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6251         EXPECT_THAT(BarLoc, IsNull());
6252       });
6253 }
6254 
6255 TEST(TransferTest, LambdaCaptureThis) {
6256   std::string Code = R"(
6257     struct Bar {
6258       int Foo;
6259 
6260       void target() {
6261         [this]() {
6262           Foo;
6263           // [[p]]
6264         }();
6265       }
6266     };
6267   )";
6268   runDataflowOnLambda(
6269       Code,
6270       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6271          ASTContext &ASTCtx) {
6272         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6273         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6274 
6275         const RecordStorageLocation *ThisPointeeLoc =
6276             Env.getThisPointeeStorageLocation();
6277         ASSERT_THAT(ThisPointeeLoc, NotNull());
6278 
6279         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6280         ASSERT_THAT(FooDecl, NotNull());
6281 
6282         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
6283         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6284 
6285         const Value *FooVal = Env.getValue(*FooLoc);
6286         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6287       });
6288 }
6289 
6290 TEST(TransferTest, DifferentReferenceLocInJoin) {
6291   // This test triggers a case where the storage location for a reference-type
6292   // variable is different for two states being joined. We used to believe this
6293   // could not happen and therefore had an assertion disallowing this; this test
6294   // exists to demonstrate that we can handle this condition without a failing
6295   // assertion. See also the discussion here:
6296   // https://discourse.llvm.org/t/70086/6
6297   std::string Code = R"(
6298     namespace std {
6299       template <class T> struct initializer_list {
6300         const T* begin();
6301         const T* end();
6302       };
6303     }
6304 
6305     void target(char* p, char* end) {
6306       while (p != end) {
6307         if (*p == ' ') {
6308           p++;
6309           continue;
6310         }
6311 
6312         auto && range = {1, 2};
6313         for (auto b = range.begin(), e = range.end(); b != e; ++b) {
6314         }
6315         (void)0;
6316         // [[p]]
6317       }
6318     }
6319   )";
6320   runDataflow(
6321       Code,
6322       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6323          ASTContext &ASTCtx) {
6324         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6325 
6326         // Joining environments with different storage locations for the same
6327         // declaration results in the declaration being removed from the joined
6328         // environment.
6329         const ValueDecl *VD = findValueDecl(ASTCtx, "range");
6330         ASSERT_EQ(Env.getStorageLocation(*VD), nullptr);
6331       });
6332 }
6333 
6334 } // namespace
6335