xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision ca1034341cfec226c09ff0e473c6ecbcc2a1194c)
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, ResultObjectLocation) {
2639   std::string Code = R"(
2640     struct A {
2641       virtual ~A() = default;
2642     };
2643 
2644     void target() {
2645       A();
2646       (void)0; // [[p]]
2647     }
2648   )";
2649   using ast_matchers::cxxBindTemporaryExpr;
2650   using ast_matchers::cxxTemporaryObjectExpr;
2651   using ast_matchers::exprWithCleanups;
2652   using ast_matchers::has;
2653   using ast_matchers::match;
2654   using ast_matchers::selectFirst;
2655   using ast_matchers::traverse;
2656   runDataflow(
2657       Code,
2658       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2659          ASTContext &ASTCtx) {
2660         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2661 
2662         // The expresssion `A()` in the code above produces the following
2663         // structure, consisting of three prvalues of record type.
2664         // `Env.getResultObjectLocation()` should return the same location for
2665         // all of these.
2666         auto MatchResult = match(
2667             traverse(TK_AsIs,
2668                      exprWithCleanups(
2669                          has(cxxBindTemporaryExpr(
2670                                  has(cxxTemporaryObjectExpr().bind("toe")))
2671                                  .bind("bte")))
2672                          .bind("ewc")),
2673             ASTCtx);
2674         auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
2675         ASSERT_NE(TOE, nullptr);
2676         auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
2677         ASSERT_NE(EWC, nullptr);
2678         auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
2679         ASSERT_NE(BTE, nullptr);
2680 
2681         RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
2682         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
2683         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
2684       });
2685 }
2686 
2687 TEST(TransferTest, StaticCast) {
2688   std::string Code = R"(
2689     void target(int Foo) {
2690       int Bar = static_cast<int>(Foo);
2691       // [[p]]
2692     }
2693   )";
2694   runDataflow(
2695       Code,
2696       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2697          ASTContext &ASTCtx) {
2698         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2699         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2700 
2701         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2702         ASSERT_THAT(FooDecl, NotNull());
2703 
2704         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2705         ASSERT_THAT(BarDecl, NotNull());
2706 
2707         const auto *FooVal = Env.getValue(*FooDecl);
2708         const auto *BarVal = Env.getValue(*BarDecl);
2709         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2710         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2711         EXPECT_EQ(FooVal, BarVal);
2712       });
2713 }
2714 
2715 TEST(TransferTest, IntegralCast) {
2716   std::string Code = R"(
2717     void target(int Foo) {
2718       long Bar = Foo;
2719       // [[p]]
2720     }
2721   )";
2722   runDataflow(
2723       Code,
2724       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2725          ASTContext &ASTCtx) {
2726         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2727         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2728 
2729         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2730         ASSERT_THAT(FooDecl, NotNull());
2731 
2732         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2733         ASSERT_THAT(BarDecl, NotNull());
2734 
2735         const auto *FooVal = Env.getValue(*FooDecl);
2736         const auto *BarVal = Env.getValue(*BarDecl);
2737         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2738         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2739         EXPECT_EQ(FooVal, BarVal);
2740       });
2741 }
2742 
2743 TEST(TransferTest, IntegraltoBooleanCast) {
2744   std::string Code = R"(
2745     void target(int Foo) {
2746       bool Bar = Foo;
2747       // [[p]]
2748     }
2749   )";
2750   runDataflow(
2751       Code,
2752       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2753          ASTContext &ASTCtx) {
2754         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2755         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2756 
2757         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2758         ASSERT_THAT(FooDecl, NotNull());
2759 
2760         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2761         ASSERT_THAT(BarDecl, NotNull());
2762 
2763         const auto *FooVal = Env.getValue(*FooDecl);
2764         const auto *BarVal = Env.getValue(*BarDecl);
2765         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2766         EXPECT_TRUE(isa<BoolValue>(BarVal));
2767       });
2768 }
2769 
2770 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2771   std::string Code = R"(
2772     void target(bool Foo) {
2773       int Zab = Foo;
2774       bool Bar = Zab;
2775       // [[p]]
2776     }
2777   )";
2778   runDataflow(
2779       Code,
2780       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2781          ASTContext &ASTCtx) {
2782         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2783         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2784 
2785         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2786         ASSERT_THAT(FooDecl, NotNull());
2787 
2788         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2789         ASSERT_THAT(BarDecl, NotNull());
2790 
2791         const auto *FooVal = Env.getValue(*FooDecl);
2792         const auto *BarVal = Env.getValue(*BarDecl);
2793         EXPECT_TRUE(isa<BoolValue>(FooVal));
2794         EXPECT_TRUE(isa<BoolValue>(BarVal));
2795         EXPECT_EQ(FooVal, BarVal);
2796       });
2797 }
2798 
2799 TEST(TransferTest, NullToPointerCast) {
2800   std::string Code = R"(
2801     using my_nullptr_t = decltype(nullptr);
2802     struct Baz {};
2803     void target() {
2804       int *FooX = nullptr;
2805       int *FooY = nullptr;
2806       bool **Bar = nullptr;
2807       Baz *Baz = nullptr;
2808       my_nullptr_t Null = 0;
2809       // [[p]]
2810     }
2811   )";
2812   runDataflow(
2813       Code,
2814       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2815          ASTContext &ASTCtx) {
2816         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2817         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2818 
2819         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2820         ASSERT_THAT(FooXDecl, NotNull());
2821 
2822         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2823         ASSERT_THAT(FooYDecl, NotNull());
2824 
2825         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2826         ASSERT_THAT(BarDecl, NotNull());
2827 
2828         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2829         ASSERT_THAT(BazDecl, NotNull());
2830 
2831         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2832         ASSERT_THAT(NullDecl, NotNull());
2833 
2834         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
2835         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
2836         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2837         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
2838         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
2839 
2840         EXPECT_EQ(FooXVal, FooYVal);
2841         EXPECT_NE(FooXVal, BarVal);
2842         EXPECT_NE(FooXVal, BazVal);
2843         EXPECT_NE(BarVal, BazVal);
2844 
2845         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2846         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2847         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2848 
2849         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2850         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2851         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2852 
2853         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2854         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
2855         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2856 
2857         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
2858         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2859         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2860       });
2861 }
2862 
2863 TEST(TransferTest, PointerToMemberVariable) {
2864   std::string Code = R"(
2865     struct S {
2866       int i;
2867     };
2868     void target() {
2869       int S::*MemberPointer = &S::i;
2870       // [[p]]
2871     }
2872   )";
2873   runDataflow(
2874       Code,
2875       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2876          ASTContext &ASTCtx) {
2877         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2878 
2879         const ValueDecl *MemberPointerDecl =
2880             findValueDecl(ASTCtx, "MemberPointer");
2881         ASSERT_THAT(MemberPointerDecl, NotNull());
2882         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2883       });
2884 }
2885 
2886 TEST(TransferTest, PointerToMemberFunction) {
2887   std::string Code = R"(
2888     struct S {
2889       void Method();
2890     };
2891     void target() {
2892       void (S::*MemberPointer)() = &S::Method;
2893       // [[p]]
2894     }
2895   )";
2896   runDataflow(
2897       Code,
2898       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2899          ASTContext &ASTCtx) {
2900         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2901 
2902         const ValueDecl *MemberPointerDecl =
2903             findValueDecl(ASTCtx, "MemberPointer");
2904         ASSERT_THAT(MemberPointerDecl, NotNull());
2905         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2906       });
2907 }
2908 
2909 TEST(TransferTest, NullToMemberPointerCast) {
2910   std::string Code = R"(
2911     struct Foo {};
2912     void target() {
2913       int Foo::*MemberPointer = nullptr;
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 *MemberPointerDecl =
2925             findValueDecl(ASTCtx, "MemberPointer");
2926         ASSERT_THAT(MemberPointerDecl, NotNull());
2927         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2928       });
2929 }
2930 
2931 TEST(TransferTest, AddrOfValue) {
2932   std::string Code = R"(
2933     void target() {
2934       int Foo;
2935       int *Bar = &Foo;
2936       // [[p]]
2937     }
2938   )";
2939   runDataflow(
2940       Code,
2941       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2942          ASTContext &ASTCtx) {
2943         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2944         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2945 
2946         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2947         ASSERT_THAT(FooDecl, NotNull());
2948 
2949         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2950         ASSERT_THAT(BarDecl, NotNull());
2951 
2952         const auto *FooLoc =
2953             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
2954         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2955         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2956       });
2957 }
2958 
2959 TEST(TransferTest, AddrOfReference) {
2960   std::string Code = R"(
2961     void target(int *Foo) {
2962       int *Bar = &(*Foo);
2963       // [[p]]
2964     }
2965   )";
2966   runDataflow(
2967       Code,
2968       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2969          ASTContext &ASTCtx) {
2970         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2971         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2972 
2973         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2974         ASSERT_THAT(FooDecl, NotNull());
2975 
2976         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2977         ASSERT_THAT(BarDecl, NotNull());
2978 
2979         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
2980         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2981         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2982       });
2983 }
2984 
2985 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
2986   std::string Code = R"(
2987     template <typename T>
2988     void target() {}
2989   )";
2990   ASSERT_THAT_ERROR(
2991       checkDataflowWithNoopAnalysis(Code),
2992       llvm::FailedWithMessage("Cannot analyze templated declarations"));
2993 }
2994 
2995 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
2996   std::string Code = R"(
2997     template <typename T>
2998     struct A {
2999       void target() {}
3000     };
3001   )";
3002   ASSERT_THAT_ERROR(
3003       checkDataflowWithNoopAnalysis(Code),
3004       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3005 }
3006 
3007 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3008   std::string Code = R"(
3009     struct A {};
3010 
3011     void target(A Foo, A Bar, bool Cond) {
3012       A Baz = Cond ?  Foo : Bar;
3013       /*[[p]]*/
3014     }
3015   )";
3016   runDataflow(
3017       Code,
3018       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3019          ASTContext &ASTCtx) {
3020         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3021         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3022 
3023         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3024         ASSERT_THAT(FooDecl, NotNull());
3025 
3026         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3027         ASSERT_THAT(BarDecl, NotNull());
3028 
3029         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3030         ASSERT_THAT(BazDecl, NotNull());
3031 
3032         const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
3033         const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
3034 
3035         const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
3036         ASSERT_THAT(BazVal, NotNull());
3037 
3038         EXPECT_NE(BazVal, FooVal);
3039         EXPECT_NE(BazVal, BarVal);
3040       });
3041 }
3042 
3043 TEST(TransferTest, VarDeclInDoWhile) {
3044   std::string Code = R"(
3045     void target(int *Foo) {
3046       do {
3047         int Bar = *Foo;
3048         // [[in_loop]]
3049       } while (false);
3050       (void)0;
3051       // [[after_loop]]
3052     }
3053   )";
3054   runDataflow(
3055       Code,
3056       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3057          ASTContext &ASTCtx) {
3058         const Environment &EnvInLoop =
3059             getEnvironmentAtAnnotation(Results, "in_loop");
3060         const Environment &EnvAfterLoop =
3061             getEnvironmentAtAnnotation(Results, "after_loop");
3062 
3063         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3064         ASSERT_THAT(FooDecl, NotNull());
3065 
3066         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3067         ASSERT_THAT(BarDecl, NotNull());
3068 
3069         const auto *FooVal =
3070             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3071         const auto *FooPointeeVal =
3072             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3073 
3074         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3075         EXPECT_EQ(BarVal, FooPointeeVal);
3076 
3077         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3078       });
3079 }
3080 
3081 TEST(TransferTest, UnreachableAfterWhileTrue) {
3082   std::string Code = R"(
3083     void target() {
3084       while (true) {}
3085       (void)0;
3086       /*[[p]]*/
3087     }
3088   )";
3089   runDataflow(
3090       Code,
3091       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3092          ASTContext &ASTCtx) {
3093         // The node after the while-true is pruned because it is trivially
3094         // known to be unreachable.
3095         ASSERT_TRUE(Results.empty());
3096       });
3097 }
3098 
3099 TEST(TransferTest, AggregateInitialization) {
3100   std::string BracesCode = R"(
3101     struct A {
3102       int Foo;
3103     };
3104 
3105     struct B {
3106       int Bar;
3107       A Baz;
3108       int Qux;
3109     };
3110 
3111     void target(int BarArg, int FooArg, int QuxArg) {
3112       B Quux{BarArg, {FooArg}, QuxArg};
3113       B OtherB;
3114       /*[[p]]*/
3115     }
3116   )";
3117   std::string BraceElisionCode = R"(
3118     struct A {
3119       int Foo;
3120     };
3121 
3122     struct B {
3123       int Bar;
3124       A Baz;
3125       int Qux;
3126     };
3127 
3128     void target(int BarArg, int FooArg, int QuxArg) {
3129       B Quux = {BarArg, FooArg, QuxArg};
3130       B OtherB;
3131       /*[[p]]*/
3132     }
3133   )";
3134   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3135     runDataflow(
3136         Code,
3137         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3138            ASTContext &ASTCtx) {
3139           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3140           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3141 
3142           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3143           ASSERT_THAT(FooDecl, NotNull());
3144 
3145           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3146           ASSERT_THAT(BarDecl, NotNull());
3147 
3148           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3149           ASSERT_THAT(BazDecl, NotNull());
3150 
3151           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3152           ASSERT_THAT(QuxDecl, NotNull());
3153 
3154           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3155           ASSERT_THAT(FooArgDecl, NotNull());
3156 
3157           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3158           ASSERT_THAT(BarArgDecl, NotNull());
3159 
3160           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3161           ASSERT_THAT(QuxArgDecl, NotNull());
3162 
3163           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3164           ASSERT_THAT(QuuxDecl, NotNull());
3165 
3166           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3167           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3168           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3169 
3170           const auto &QuuxLoc =
3171               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3172           const auto &BazLoc =
3173               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3174 
3175           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3176           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3177           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3178 
3179           // Check that fields initialized in an initializer list are always
3180           // modeled in other instances of the same type.
3181           const auto &OtherBLoc =
3182               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3183           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3184           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3185           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3186         });
3187   }
3188 }
3189 
3190 TEST(TransferTest, AggregateInitializationReferenceField) {
3191   std::string Code = R"(
3192     struct S {
3193       int &RefField;
3194     };
3195 
3196     void target(int i) {
3197       S s = { i };
3198       /*[[p]]*/
3199     }
3200   )";
3201   runDataflow(
3202       Code,
3203       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3204          ASTContext &ASTCtx) {
3205         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3206 
3207         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3208 
3209         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3210         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3211 
3212         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3213       });
3214 }
3215 
3216 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3217   std::string Code = R"(
3218     struct S {
3219       int i1;
3220       int i2;
3221     };
3222 
3223     void target(int i) {
3224       S s = { i };
3225       /*[[p]]*/
3226     }
3227   )";
3228   runDataflow(
3229       Code,
3230       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3231          ASTContext &ASTCtx) {
3232         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3233 
3234         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3235         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3236 
3237         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3238 
3239         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3240         auto &I1Value =
3241             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3242         EXPECT_EQ(&I1Value, &IValue);
3243         auto &I2Value =
3244             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3245         EXPECT_NE(&I2Value, &IValue);
3246       });
3247 }
3248 
3249 TEST(TransferTest, AggregateInitializationFunctionPointer) {
3250   // This is a repro for an assertion failure.
3251   // nullptr takes on the type of a const function pointer, but its type was
3252   // asserted to be equal to the *unqualified* type of Field, which no longer
3253   // included the const.
3254   std::string Code = R"(
3255     struct S {
3256       void (*const Field)();
3257     };
3258 
3259     void target() {
3260       S s{nullptr};
3261     }
3262   )";
3263   runDataflow(
3264       Code,
3265       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3266          ASTContext &ASTCtx) {});
3267 }
3268 
3269 TEST(TransferTest, AssignToUnionMember) {
3270   std::string Code = R"(
3271     union A {
3272       int Foo;
3273     };
3274 
3275     void target(int Bar) {
3276       A Baz;
3277       Baz.Foo = Bar;
3278       // [[p]]
3279     }
3280   )";
3281   runDataflow(
3282       Code,
3283       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3284          ASTContext &ASTCtx) {
3285         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3286         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3287 
3288         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3289         ASSERT_THAT(BazDecl, NotNull());
3290         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3291 
3292         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3293         FieldDecl *FooDecl = nullptr;
3294         for (FieldDecl *Field : BazFields) {
3295           if (Field->getNameAsString() == "Foo") {
3296             FooDecl = Field;
3297           } else {
3298             FAIL() << "Unexpected field: " << Field->getNameAsString();
3299           }
3300         }
3301         ASSERT_THAT(FooDecl, NotNull());
3302 
3303         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
3304             Env.getStorageLocation(*BazDecl));
3305         ASSERT_THAT(BazLoc, NotNull());
3306         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
3307 
3308         const auto *FooVal =
3309             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
3310 
3311         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3312         ASSERT_THAT(BarDecl, NotNull());
3313         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
3314         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3315 
3316         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
3317       });
3318 }
3319 
3320 TEST(TransferTest, AssignFromBoolLiteral) {
3321   std::string Code = R"(
3322     void target() {
3323       bool Foo = true;
3324       bool Bar = false;
3325       // [[p]]
3326     }
3327   )";
3328   runDataflow(
3329       Code,
3330       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3331          ASTContext &ASTCtx) {
3332         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3333         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3334 
3335         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3336         ASSERT_THAT(FooDecl, NotNull());
3337 
3338         const auto *FooVal =
3339             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3340         ASSERT_THAT(FooVal, NotNull());
3341 
3342         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3343         ASSERT_THAT(BarDecl, NotNull());
3344 
3345         const auto *BarVal =
3346             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3347         ASSERT_THAT(BarVal, NotNull());
3348 
3349         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3350         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3351       });
3352 }
3353 
3354 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3355   {
3356     std::string Code = R"(
3357     void target(bool Foo, bool Bar, bool Qux) {
3358       bool Baz = (Foo) && (Bar || Qux);
3359       // [[p]]
3360     }
3361   )";
3362     runDataflow(
3363         Code,
3364         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3365            ASTContext &ASTCtx) {
3366           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3367           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3368 
3369           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3370           ASSERT_THAT(FooDecl, NotNull());
3371 
3372           const auto *FooVal =
3373               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3374           ASSERT_THAT(FooVal, NotNull());
3375 
3376           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3377           ASSERT_THAT(BarDecl, NotNull());
3378 
3379           const auto *BarVal =
3380               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3381           ASSERT_THAT(BarVal, NotNull());
3382 
3383           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3384           ASSERT_THAT(QuxDecl, NotNull());
3385 
3386           const auto *QuxVal =
3387               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3388           ASSERT_THAT(QuxVal, NotNull());
3389 
3390           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3391           ASSERT_THAT(BazDecl, NotNull());
3392 
3393           const auto *BazVal =
3394               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3395           ASSERT_THAT(BazVal, NotNull());
3396           auto &A = Env.arena();
3397           EXPECT_EQ(&BazVal->formula(),
3398                     &A.makeAnd(FooVal->formula(),
3399                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3400         });
3401   }
3402 
3403   {
3404     std::string Code = R"(
3405     void target(bool Foo, bool Bar, bool Qux) {
3406       bool Baz = (Foo && Qux) || (Bar);
3407       // [[p]]
3408     }
3409   )";
3410     runDataflow(
3411         Code,
3412         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3413            ASTContext &ASTCtx) {
3414           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3415           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3416 
3417           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3418           ASSERT_THAT(FooDecl, NotNull());
3419 
3420           const auto *FooVal =
3421               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3422           ASSERT_THAT(FooVal, NotNull());
3423 
3424           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3425           ASSERT_THAT(BarDecl, NotNull());
3426 
3427           const auto *BarVal =
3428               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3429           ASSERT_THAT(BarVal, NotNull());
3430 
3431           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3432           ASSERT_THAT(QuxDecl, NotNull());
3433 
3434           const auto *QuxVal =
3435               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3436           ASSERT_THAT(QuxVal, NotNull());
3437 
3438           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3439           ASSERT_THAT(BazDecl, NotNull());
3440 
3441           const auto *BazVal =
3442               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3443           ASSERT_THAT(BazVal, NotNull());
3444           auto &A = Env.arena();
3445           EXPECT_EQ(&BazVal->formula(),
3446                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3447                               BarVal->formula()));
3448         });
3449   }
3450 
3451   {
3452     std::string Code = R"(
3453       void target(bool A, bool B, bool C, bool D) {
3454         bool Foo = ((A && B) && C) && D;
3455         // [[p]]
3456       }
3457     )";
3458     runDataflow(
3459         Code,
3460         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3461            ASTContext &ASTCtx) {
3462           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3463           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3464 
3465           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
3466           ASSERT_THAT(ADecl, NotNull());
3467 
3468           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
3469           ASSERT_THAT(AVal, NotNull());
3470 
3471           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3472           ASSERT_THAT(BDecl, NotNull());
3473 
3474           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
3475           ASSERT_THAT(BVal, NotNull());
3476 
3477           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3478           ASSERT_THAT(CDecl, NotNull());
3479 
3480           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3481           ASSERT_THAT(CVal, NotNull());
3482 
3483           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3484           ASSERT_THAT(DDecl, NotNull());
3485 
3486           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3487           ASSERT_THAT(DVal, NotNull());
3488 
3489           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3490           ASSERT_THAT(FooDecl, NotNull());
3491 
3492           const auto *FooVal =
3493               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3494           ASSERT_THAT(FooVal, NotNull());
3495           auto &A = Env.arena();
3496           EXPECT_EQ(
3497               &FooVal->formula(),
3498               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
3499                                    CVal->formula()),
3500                          DVal->formula()));
3501         });
3502   }
3503 }
3504 
3505 TEST(TransferTest, AssignFromBoolNegation) {
3506   std::string Code = R"(
3507     void target() {
3508       bool Foo = true;
3509       bool Bar = !(Foo);
3510       // [[p]]
3511     }
3512   )";
3513   runDataflow(
3514       Code,
3515       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3516          ASTContext &ASTCtx) {
3517         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3518         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3519 
3520         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3521         ASSERT_THAT(FooDecl, NotNull());
3522 
3523         const auto *FooVal =
3524             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3525         ASSERT_THAT(FooVal, NotNull());
3526 
3527         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3528         ASSERT_THAT(BarDecl, NotNull());
3529 
3530         const auto *BarVal =
3531             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3532         ASSERT_THAT(BarVal, NotNull());
3533         auto &A = Env.arena();
3534         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
3535       });
3536 }
3537 
3538 TEST(TransferTest, BuiltinExpect) {
3539   std::string Code = R"(
3540     void target(long Foo) {
3541       long Bar = __builtin_expect(Foo, true);
3542       /*[[p]]*/
3543     }
3544   )";
3545   runDataflow(
3546       Code,
3547       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3548          ASTContext &ASTCtx) {
3549         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3550         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3551 
3552         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3553         ASSERT_THAT(FooDecl, NotNull());
3554 
3555         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3556         ASSERT_THAT(BarDecl, NotNull());
3557 
3558         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3559       });
3560 }
3561 
3562 // `__builtin_expect` takes and returns a `long` argument, so other types
3563 // involve casts. This verifies that we identify the input and output in that
3564 // case.
3565 TEST(TransferTest, BuiltinExpectBoolArg) {
3566   std::string Code = R"(
3567     void target(bool Foo) {
3568       bool Bar = __builtin_expect(Foo, true);
3569       /*[[p]]*/
3570     }
3571   )";
3572   runDataflow(
3573       Code,
3574       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3575          ASTContext &ASTCtx) {
3576         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3577         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3578 
3579         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3580         ASSERT_THAT(FooDecl, NotNull());
3581 
3582         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3583         ASSERT_THAT(BarDecl, NotNull());
3584 
3585         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3586       });
3587 }
3588 
3589 TEST(TransferTest, BuiltinUnreachable) {
3590   std::string Code = R"(
3591     void target(bool Foo) {
3592       bool Bar = false;
3593       if (Foo)
3594         Bar = Foo;
3595       else
3596         __builtin_unreachable();
3597       (void)0;
3598       /*[[p]]*/
3599     }
3600   )";
3601   runDataflow(
3602       Code,
3603       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3604          ASTContext &ASTCtx) {
3605         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3606         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3607 
3608         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3609         ASSERT_THAT(FooDecl, NotNull());
3610 
3611         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3612         ASSERT_THAT(BarDecl, NotNull());
3613 
3614         // `__builtin_unreachable` promises that the code is
3615         // unreachable, so the compiler treats the "then" branch as the
3616         // only possible predecessor of this statement.
3617         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3618       });
3619 }
3620 
3621 TEST(TransferTest, BuiltinTrap) {
3622   std::string Code = R"(
3623     void target(bool Foo) {
3624       bool Bar = false;
3625       if (Foo)
3626         Bar = Foo;
3627       else
3628         __builtin_trap();
3629       (void)0;
3630       /*[[p]]*/
3631     }
3632   )";
3633   runDataflow(
3634       Code,
3635       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3636          ASTContext &ASTCtx) {
3637         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3638         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3639 
3640         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3641         ASSERT_THAT(FooDecl, NotNull());
3642 
3643         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3644         ASSERT_THAT(BarDecl, NotNull());
3645 
3646         // `__builtin_trap` ensures program termination, so only the
3647         // "then" branch is a predecessor of this statement.
3648         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3649       });
3650 }
3651 
3652 TEST(TransferTest, BuiltinDebugTrap) {
3653   std::string Code = R"(
3654     void target(bool Foo) {
3655       bool Bar = false;
3656       if (Foo)
3657         Bar = Foo;
3658       else
3659         __builtin_debugtrap();
3660       (void)0;
3661       /*[[p]]*/
3662     }
3663   )";
3664   runDataflow(
3665       Code,
3666       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3667          ASTContext &ASTCtx) {
3668         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3669         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3670 
3671         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3672         ASSERT_THAT(FooDecl, NotNull());
3673 
3674         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3675         ASSERT_THAT(BarDecl, NotNull());
3676 
3677         // `__builtin_debugtrap` doesn't ensure program termination.
3678         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3679       });
3680 }
3681 
3682 TEST(TransferTest, StaticIntSingleVarDecl) {
3683   std::string Code = R"(
3684     void target() {
3685       static int Foo;
3686       // [[p]]
3687     }
3688   )";
3689   runDataflow(
3690       Code,
3691       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3692          ASTContext &ASTCtx) {
3693         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3694         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3695 
3696         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3697         ASSERT_THAT(FooDecl, NotNull());
3698 
3699         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3700         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3701 
3702         const Value *FooVal = Env.getValue(*FooLoc);
3703         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3704       });
3705 }
3706 
3707 TEST(TransferTest, StaticIntGroupVarDecl) {
3708   std::string Code = R"(
3709     void target() {
3710       static int Foo, Bar;
3711       (void)0;
3712       // [[p]]
3713     }
3714   )";
3715   runDataflow(
3716       Code,
3717       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3718          ASTContext &ASTCtx) {
3719         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3720         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3721 
3722         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3723         ASSERT_THAT(FooDecl, NotNull());
3724 
3725         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3726         ASSERT_THAT(BarDecl, NotNull());
3727 
3728         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3729         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3730 
3731         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3732         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3733 
3734         const Value *FooVal = Env.getValue(*FooLoc);
3735         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3736 
3737         const Value *BarVal = Env.getValue(*BarLoc);
3738         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3739 
3740         EXPECT_NE(FooVal, BarVal);
3741       });
3742 }
3743 
3744 TEST(TransferTest, GlobalIntVarDecl) {
3745   std::string Code = R"(
3746     static int Foo;
3747 
3748     void target() {
3749       int Bar = Foo;
3750       int Baz = Foo;
3751       // [[p]]
3752     }
3753   )";
3754   runDataflow(
3755       Code,
3756       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3757          ASTContext &ASTCtx) {
3758         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3759         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3760 
3761         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3762         ASSERT_THAT(BarDecl, NotNull());
3763 
3764         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3765         ASSERT_THAT(BazDecl, NotNull());
3766 
3767         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3768         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3769         EXPECT_EQ(BarVal, BazVal);
3770       });
3771 }
3772 
3773 TEST(TransferTest, StaticMemberIntVarDecl) {
3774   std::string Code = R"(
3775     struct A {
3776       static int Foo;
3777     };
3778 
3779     void target(A a) {
3780       int Bar = a.Foo;
3781       int Baz = a.Foo;
3782       // [[p]]
3783     }
3784   )";
3785   runDataflow(
3786       Code,
3787       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3788          ASTContext &ASTCtx) {
3789         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3790         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3791 
3792         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3793         ASSERT_THAT(BarDecl, NotNull());
3794 
3795         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3796         ASSERT_THAT(BazDecl, NotNull());
3797 
3798         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3799         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3800         EXPECT_EQ(BarVal, BazVal);
3801       });
3802 }
3803 
3804 TEST(TransferTest, StaticMemberRefVarDecl) {
3805   std::string Code = R"(
3806     struct A {
3807       static int &Foo;
3808     };
3809 
3810     void target(A a) {
3811       int Bar = a.Foo;
3812       int Baz = a.Foo;
3813       // [[p]]
3814     }
3815   )";
3816   runDataflow(
3817       Code,
3818       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3819          ASTContext &ASTCtx) {
3820         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3821         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3822 
3823         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3824         ASSERT_THAT(BarDecl, NotNull());
3825 
3826         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3827         ASSERT_THAT(BazDecl, NotNull());
3828 
3829         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3830         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3831         EXPECT_EQ(BarVal, BazVal);
3832       });
3833 }
3834 
3835 TEST(TransferTest, AssignMemberBeforeCopy) {
3836   std::string Code = R"(
3837     struct A {
3838       int Foo;
3839     };
3840 
3841     void target() {
3842       A A1;
3843       A A2;
3844       int Bar;
3845       A1.Foo = Bar;
3846       A2 = A1;
3847       // [[p]]
3848     }
3849   )";
3850   runDataflow(
3851       Code,
3852       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3853          ASTContext &ASTCtx) {
3854         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3855         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3856 
3857         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3858         ASSERT_THAT(FooDecl, NotNull());
3859 
3860         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3861         ASSERT_THAT(BarDecl, NotNull());
3862 
3863         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3864         ASSERT_THAT(A1Decl, NotNull());
3865 
3866         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3867         ASSERT_THAT(A2Decl, NotNull());
3868 
3869         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3870 
3871         const auto &A2Loc =
3872             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
3873         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
3874       });
3875 }
3876 
3877 TEST(TransferTest, BooleanEquality) {
3878   std::string Code = R"(
3879     void target(bool Bar) {
3880       bool Foo = true;
3881       if (Bar == Foo) {
3882         (void)0;
3883         /*[[p-then]]*/
3884       } else {
3885         (void)0;
3886         /*[[p-else]]*/
3887       }
3888     }
3889   )";
3890   runDataflow(
3891       Code,
3892       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3893          ASTContext &ASTCtx) {
3894         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3895         const Environment &EnvThen =
3896             getEnvironmentAtAnnotation(Results, "p-then");
3897         const Environment &EnvElse =
3898             getEnvironmentAtAnnotation(Results, "p-else");
3899 
3900         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3901         ASSERT_THAT(BarDecl, NotNull());
3902 
3903         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3904         EXPECT_TRUE(EnvThen.proves(BarValThen));
3905 
3906         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3907         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
3908       });
3909 }
3910 
3911 TEST(TransferTest, BooleanInequality) {
3912   std::string Code = R"(
3913     void target(bool Bar) {
3914       bool Foo = true;
3915       if (Bar != Foo) {
3916         (void)0;
3917         /*[[p-then]]*/
3918       } else {
3919         (void)0;
3920         /*[[p-else]]*/
3921       }
3922     }
3923   )";
3924   runDataflow(
3925       Code,
3926       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3927          ASTContext &ASTCtx) {
3928         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3929         const Environment &EnvThen =
3930             getEnvironmentAtAnnotation(Results, "p-then");
3931         const Environment &EnvElse =
3932             getEnvironmentAtAnnotation(Results, "p-else");
3933 
3934         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3935         ASSERT_THAT(BarDecl, NotNull());
3936 
3937         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3938         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
3939 
3940         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3941         EXPECT_TRUE(EnvElse.proves(BarValElse));
3942       });
3943 }
3944 
3945 TEST(TransferTest, IntegerLiteralEquality) {
3946   std::string Code = R"(
3947     void target() {
3948       bool equal = (42 == 42);
3949       // [[p]]
3950     }
3951   )";
3952   runDataflow(
3953       Code,
3954       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3955          ASTContext &ASTCtx) {
3956         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3957 
3958         auto &Equal =
3959             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
3960         EXPECT_TRUE(Env.proves(Equal));
3961       });
3962 }
3963 
3964 TEST(TransferTest, CorrelatedBranches) {
3965   std::string Code = R"(
3966     void target(bool B, bool C) {
3967       if (B) {
3968         return;
3969       }
3970       (void)0;
3971       /*[[p0]]*/
3972       if (C) {
3973         B = true;
3974         /*[[p1]]*/
3975       }
3976       if (B) {
3977         (void)0;
3978         /*[[p2]]*/
3979       }
3980     }
3981   )";
3982   runDataflow(
3983       Code,
3984       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3985          ASTContext &ASTCtx) {
3986         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3987 
3988         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3989         ASSERT_THAT(CDecl, NotNull());
3990 
3991         {
3992           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3993           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3994           ASSERT_THAT(BDecl, NotNull());
3995           auto &BVal = getFormula(*BDecl, Env);
3996 
3997           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
3998         }
3999 
4000         {
4001           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4002           auto &CVal = getFormula(*CDecl, Env);
4003           EXPECT_TRUE(Env.proves(CVal));
4004         }
4005 
4006         {
4007           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4008           auto &CVal = getFormula(*CDecl, Env);
4009           EXPECT_TRUE(Env.proves(CVal));
4010         }
4011       });
4012 }
4013 
4014 TEST(TransferTest, LoopWithAssignmentConverges) {
4015   std::string Code = R"(
4016     bool foo();
4017 
4018     void target() {
4019        do {
4020         bool Bar = foo();
4021         if (Bar) break;
4022         (void)Bar;
4023         /*[[p]]*/
4024       } while (true);
4025     }
4026   )";
4027   // The key property that we are verifying is implicit in `runDataflow` --
4028   // namely, that the analysis succeeds, rather than hitting the maximum number
4029   // of iterations.
4030   runDataflow(
4031       Code,
4032       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4033          ASTContext &ASTCtx) {
4034         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4035         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4036 
4037         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4038         ASSERT_THAT(BarDecl, NotNull());
4039 
4040         auto &BarVal = getFormula(*BarDecl, Env);
4041         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4042       });
4043 }
4044 
4045 TEST(TransferTest, LoopWithStagedAssignments) {
4046   std::string Code = R"(
4047     bool foo();
4048 
4049     void target() {
4050       bool Bar = false;
4051       bool Err = false;
4052       while (foo()) {
4053         if (Bar)
4054           Err = true;
4055         Bar = true;
4056         /*[[p]]*/
4057       }
4058     }
4059   )";
4060   runDataflow(
4061       Code,
4062       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4063          ASTContext &ASTCtx) {
4064         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4065         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4066 
4067         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4068         ASSERT_THAT(BarDecl, NotNull());
4069         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4070         ASSERT_THAT(ErrDecl, NotNull());
4071 
4072         auto &BarVal = getFormula(*BarDecl, Env);
4073         auto &ErrVal = getFormula(*ErrDecl, Env);
4074         EXPECT_TRUE(Env.proves(BarVal));
4075         // An unsound analysis, for example only evaluating the loop once, can
4076         // conclude that `Err` is false. So, we test that this conclusion is not
4077         // reached.
4078         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4079       });
4080 }
4081 
4082 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4083   std::string Code = R"(
4084     bool &foo();
4085 
4086     void target() {
4087        do {
4088         bool& Bar = foo();
4089         if (Bar) break;
4090         (void)Bar;
4091         /*[[p]]*/
4092       } while (true);
4093     }
4094   )";
4095   // The key property that we are verifying is that the analysis succeeds,
4096   // rather than hitting the maximum number of iterations.
4097   runDataflow(
4098       Code,
4099       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4100          ASTContext &ASTCtx) {
4101         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4102         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4103 
4104         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4105         ASSERT_THAT(BarDecl, NotNull());
4106 
4107         auto &BarVal = getFormula(*BarDecl, Env);
4108         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4109       });
4110 }
4111 
4112 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4113   std::string Code = R"(
4114     struct Lookup {
4115       int x;
4116     };
4117 
4118     void target(Lookup val, bool b) {
4119       const Lookup* l = nullptr;
4120       while (b) {
4121         l = &val;
4122         /*[[p-inner]]*/
4123       }
4124       (void)0;
4125       /*[[p-outer]]*/
4126     }
4127   )";
4128   // The key property that we are verifying is implicit in `runDataflow` --
4129   // namely, that the analysis succeeds, rather than hitting the maximum number
4130   // of iterations.
4131   runDataflow(
4132       Code,
4133       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4134          ASTContext &ASTCtx) {
4135         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4136         const Environment &InnerEnv =
4137             getEnvironmentAtAnnotation(Results, "p-inner");
4138         const Environment &OuterEnv =
4139             getEnvironmentAtAnnotation(Results, "p-outer");
4140 
4141         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4142         ASSERT_THAT(ValDecl, NotNull());
4143 
4144         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4145         ASSERT_THAT(LDecl, NotNull());
4146 
4147         // Inner.
4148         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4149         ASSERT_THAT(LVal, NotNull());
4150 
4151         EXPECT_EQ(&LVal->getPointeeLoc(),
4152                   InnerEnv.getStorageLocation(*ValDecl));
4153 
4154         // Outer.
4155         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4156         ASSERT_THAT(LVal, NotNull());
4157 
4158         // The loop body may not have been executed, so we should not conclude
4159         // that `l` points to `val`.
4160         EXPECT_NE(&LVal->getPointeeLoc(),
4161                   OuterEnv.getStorageLocation(*ValDecl));
4162       });
4163 }
4164 
4165 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4166   std::string Code = R"cc(
4167     bool some_condition();
4168 
4169     void target(int i1, int i2) {
4170       int *p = &i1;
4171       while (true) {
4172         (void)*p;
4173         if (some_condition())
4174           p = &i1;
4175         else
4176           p = &i2;
4177       }
4178     }
4179   )cc";
4180   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4181 }
4182 
4183 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4184   std::string Code = R"cc(
4185     struct Lookup {
4186       int x;
4187     };
4188 
4189     bool some_condition();
4190 
4191     void target(Lookup l1, Lookup l2) {
4192       Lookup *l = &l1;
4193       while (true) {
4194         (void)l->x;
4195         if (some_condition())
4196           l = &l1;
4197         else
4198           l = &l2;
4199       }
4200     }
4201   )cc";
4202   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4203 }
4204 
4205 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4206   std::string Code = R"cc(
4207     bool foo();
4208 
4209     void target() {
4210       bool c = false;
4211       while (foo() || foo()) {
4212         c = true;
4213       }
4214     }
4215   )cc";
4216   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4217 }
4218 
4219 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
4220   // Check that we can prove `b` is always false in the loop.
4221   // This test exercises the logic in `widenDistinctValues()` that preserves
4222   // information if the boolean can be proved to be either true or false in both
4223   // the previous and current iteration.
4224   std::string Code = R"cc(
4225     int return_int();
4226     void target() {
4227       bool b = return_int() == 0;
4228       if (b) return;
4229       while (true) {
4230         b;
4231         // [[p]]
4232         b = return_int() == 0;
4233         if (b) return;
4234       }
4235     }
4236   )cc";
4237   runDataflow(
4238       Code,
4239       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4240          ASTContext &ASTCtx) {
4241         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4242         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
4243         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
4244       });
4245 }
4246 
4247 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4248   std::string Code = R"(
4249     union Union {
4250       int A;
4251       float B;
4252     };
4253 
4254     void foo() {
4255       Union A;
4256       Union B;
4257       A = B;
4258     }
4259   )";
4260   // This is a crash regression test when calling the transfer function on a
4261   // `CXXThisExpr` that refers to a union.
4262   runDataflow(
4263       Code,
4264       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4265          ASTContext &) {},
4266       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4267 }
4268 
4269 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4270   std::string Code = R"(
4271     struct A {
4272       int Foo;
4273       int Bar;
4274     };
4275 
4276     void target() {
4277       int Qux;
4278       A Baz;
4279       Baz.Foo = Qux;
4280       auto &FooRef = Baz.Foo;
4281       auto &BarRef = Baz.Bar;
4282       auto &[BoundFooRef, BoundBarRef] = Baz;
4283       // [[p]]
4284     }
4285   )";
4286   runDataflow(
4287       Code,
4288       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4289          ASTContext &ASTCtx) {
4290         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4291         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4292 
4293         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4294         ASSERT_THAT(FooRefDecl, NotNull());
4295 
4296         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4297         ASSERT_THAT(BarRefDecl, NotNull());
4298 
4299         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4300         ASSERT_THAT(QuxDecl, NotNull());
4301 
4302         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4303         ASSERT_THAT(BoundFooRefDecl, NotNull());
4304 
4305         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4306         ASSERT_THAT(BoundBarRefDecl, NotNull());
4307 
4308         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4309         ASSERT_THAT(FooRefLoc, NotNull());
4310 
4311         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4312         ASSERT_THAT(BarRefLoc, NotNull());
4313 
4314         const Value *QuxVal = Env.getValue(*QuxDecl);
4315         ASSERT_THAT(QuxVal, NotNull());
4316 
4317         const StorageLocation *BoundFooRefLoc =
4318             Env.getStorageLocation(*BoundFooRefDecl);
4319         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4320 
4321         const StorageLocation *BoundBarRefLoc =
4322             Env.getStorageLocation(*BoundBarRefDecl);
4323         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4324 
4325         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4326       });
4327 }
4328 
4329 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4330   std::string Code = R"(
4331     struct A {
4332       int &Foo;
4333       int &Bar;
4334     };
4335 
4336     void target(A Baz) {
4337       int Qux;
4338       Baz.Foo = Qux;
4339       auto &FooRef = Baz.Foo;
4340       auto &BarRef = Baz.Bar;
4341       auto &[BoundFooRef, BoundBarRef] = Baz;
4342       // [[p]]
4343     }
4344   )";
4345   runDataflow(
4346       Code,
4347       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4348          ASTContext &ASTCtx) {
4349         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4350         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4351 
4352         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4353         ASSERT_THAT(FooRefDecl, NotNull());
4354 
4355         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4356         ASSERT_THAT(BarRefDecl, NotNull());
4357 
4358         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4359         ASSERT_THAT(QuxDecl, NotNull());
4360 
4361         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4362         ASSERT_THAT(BoundFooRefDecl, NotNull());
4363 
4364         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4365         ASSERT_THAT(BoundBarRefDecl, NotNull());
4366 
4367         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4368         ASSERT_THAT(FooRefLoc, NotNull());
4369 
4370         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4371         ASSERT_THAT(BarRefLoc, NotNull());
4372 
4373         const Value *QuxVal = Env.getValue(*QuxDecl);
4374         ASSERT_THAT(QuxVal, NotNull());
4375 
4376         const StorageLocation *BoundFooRefLoc =
4377             Env.getStorageLocation(*BoundFooRefDecl);
4378         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4379 
4380         const StorageLocation *BoundBarRefLoc =
4381             Env.getStorageLocation(*BoundBarRefDecl);
4382         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4383 
4384         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4385       });
4386 }
4387 
4388 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4389   std::string Code = R"(
4390     struct A {
4391       int Foo;
4392       int Bar;
4393     };
4394 
4395     void target() {
4396       int Qux;
4397       A Baz;
4398       Baz.Foo = Qux;
4399       auto &FooRef = Baz.Foo;
4400       auto &BarRef = Baz.Bar;
4401       auto [BoundFoo, BoundBar] = Baz;
4402       // [[p]]
4403     }
4404   )";
4405   runDataflow(
4406       Code,
4407       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4408          ASTContext &ASTCtx) {
4409         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4410         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4411 
4412         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4413         ASSERT_THAT(FooRefDecl, NotNull());
4414 
4415         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4416         ASSERT_THAT(BarRefDecl, NotNull());
4417 
4418         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4419         ASSERT_THAT(BoundFooDecl, NotNull());
4420 
4421         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4422         ASSERT_THAT(BoundBarDecl, NotNull());
4423 
4424         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4425         ASSERT_THAT(QuxDecl, NotNull());
4426 
4427         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4428         ASSERT_THAT(FooRefLoc, NotNull());
4429 
4430         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4431         ASSERT_THAT(BarRefLoc, NotNull());
4432 
4433         const Value *QuxVal = Env.getValue(*QuxDecl);
4434         ASSERT_THAT(QuxVal, NotNull());
4435 
4436         const StorageLocation *BoundFooLoc =
4437             Env.getStorageLocation(*BoundFooDecl);
4438         EXPECT_NE(BoundFooLoc, FooRefLoc);
4439 
4440         const StorageLocation *BoundBarLoc =
4441             Env.getStorageLocation(*BoundBarDecl);
4442         EXPECT_NE(BoundBarLoc, BarRefLoc);
4443 
4444         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4445       });
4446 }
4447 
4448 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4449   std::string Code = R"(
4450     namespace std {
4451     using size_t = int;
4452     template <class> struct tuple_size;
4453     template <std::size_t, class> struct tuple_element;
4454     template <class...> class tuple;
4455 
4456     namespace {
4457     template <class T, T v>
4458     struct size_helper { static const T value = v; };
4459     } // namespace
4460 
4461     template <class... T>
4462     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4463 
4464     template <std::size_t I, class... T>
4465     struct tuple_element<I, tuple<T...>> {
4466       using type =  __type_pack_element<I, T...>;
4467     };
4468 
4469     template <class...> class tuple {};
4470 
4471     template <std::size_t I, class... T>
4472     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4473     } // namespace std
4474 
4475     std::tuple<bool, int> makeTuple();
4476 
4477     void target(bool B) {
4478       auto [BoundFoo, BoundBar] = makeTuple();
4479       bool Baz;
4480       // Include if-then-else to test interaction of `BindingDecl` with join.
4481       if (B) {
4482         Baz = BoundFoo;
4483         (void)BoundBar;
4484         // [[p1]]
4485       } else {
4486         Baz = BoundFoo;
4487       }
4488       (void)0;
4489       // [[p2]]
4490     }
4491   )";
4492   runDataflow(
4493       Code,
4494       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4495          ASTContext &ASTCtx) {
4496         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4497         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4498 
4499         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4500         ASSERT_THAT(BoundFooDecl, NotNull());
4501 
4502         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4503         ASSERT_THAT(BoundBarDecl, NotNull());
4504 
4505         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4506         ASSERT_THAT(BazDecl, NotNull());
4507 
4508         // BindingDecls always map to references -- either lvalue or rvalue, so
4509         // we still need to skip here.
4510         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4511         ASSERT_THAT(BoundFooValue, NotNull());
4512         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4513 
4514         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4515         ASSERT_THAT(BoundBarValue, NotNull());
4516         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4517 
4518         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4519         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4520 
4521         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4522 
4523         // Test that `BoundFooDecl` retains the value we expect, after the join.
4524         BoundFooValue = Env2.getValue(*BoundFooDecl);
4525         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4526       });
4527 }
4528 
4529 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4530   std::string Code = R"(
4531     namespace std {
4532     using size_t = int;
4533     template <class> struct tuple_size;
4534     template <std::size_t, class> struct tuple_element;
4535     template <class...> class tuple;
4536 
4537     namespace {
4538     template <class T, T v>
4539     struct size_helper { static const T value = v; };
4540     } // namespace
4541 
4542     template <class... T>
4543     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4544 
4545     template <std::size_t I, class... T>
4546     struct tuple_element<I, tuple<T...>> {
4547       using type =  __type_pack_element<I, T...>;
4548     };
4549 
4550     template <class...> class tuple {};
4551 
4552     template <std::size_t I, class... T>
4553     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4554     } // namespace std
4555 
4556     std::tuple<bool, int> &getTuple();
4557 
4558     void target(bool B) {
4559       auto &[BoundFoo, BoundBar] = getTuple();
4560       bool Baz;
4561       // Include if-then-else to test interaction of `BindingDecl` with join.
4562       if (B) {
4563         Baz = BoundFoo;
4564         (void)BoundBar;
4565         // [[p1]]
4566       } else {
4567         Baz = BoundFoo;
4568       }
4569       (void)0;
4570       // [[p2]]
4571     }
4572   )";
4573   runDataflow(
4574       Code,
4575       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4576          ASTContext &ASTCtx) {
4577         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4578         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4579 
4580         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4581         ASSERT_THAT(BoundFooDecl, NotNull());
4582 
4583         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4584         ASSERT_THAT(BoundBarDecl, NotNull());
4585 
4586         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4587         ASSERT_THAT(BazDecl, NotNull());
4588 
4589         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4590         ASSERT_THAT(BoundFooValue, NotNull());
4591         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4592 
4593         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4594         ASSERT_THAT(BoundBarValue, NotNull());
4595         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4596 
4597         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4598         // works as expected. We don't test aliasing properties of the
4599         // reference, because we don't model `std::get` and so have no way to
4600         // equate separate references into the tuple.
4601         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4602 
4603         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4604 
4605         // Test that `BoundFooDecl` retains the value we expect, after the join.
4606         BoundFooValue = Env2.getValue(*BoundFooDecl);
4607         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4608       });
4609 }
4610 
4611 TEST(TransferTest, BinaryOperatorComma) {
4612   std::string Code = R"(
4613     void target(int Foo, int Bar) {
4614       int &Baz = (Foo, Bar);
4615       // [[p]]
4616     }
4617   )";
4618   runDataflow(
4619       Code,
4620       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4621          ASTContext &ASTCtx) {
4622         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4623         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4624 
4625         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4626         ASSERT_THAT(BarDecl, NotNull());
4627 
4628         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4629         ASSERT_THAT(BazDecl, NotNull());
4630 
4631         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4632         ASSERT_THAT(BarLoc, NotNull());
4633 
4634         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4635         EXPECT_EQ(BazLoc, BarLoc);
4636       });
4637 }
4638 
4639 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4640   std::string Code = R"(
4641     void target(bool Foo) {
4642       if (Foo) {
4643         (void)0;
4644         // [[if_then]]
4645       } else {
4646         (void)0;
4647         // [[if_else]]
4648       }
4649     }
4650   )";
4651   runDataflow(
4652       Code,
4653       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4654          ASTContext &ASTCtx) {
4655         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4656         const Environment &ThenEnv =
4657             getEnvironmentAtAnnotation(Results, "if_then");
4658         const Environment &ElseEnv =
4659             getEnvironmentAtAnnotation(Results, "if_else");
4660 
4661         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4662         ASSERT_THAT(FooDecl, NotNull());
4663 
4664         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
4665         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
4666 
4667         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
4668         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
4669       });
4670 }
4671 
4672 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4673   std::string Code = R"(
4674     void target(bool Foo) {
4675       while (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, DoWhileStmtBranchExtendsFlowCondition) {
4707   std::string Code = R"(
4708     void target(bool Foo) {
4709       bool Bar = true;
4710       do {
4711         (void)0;
4712         // [[loop_body]]
4713         Bar = false;
4714       } while (Foo);
4715       (void)0;
4716       // [[after_loop]]
4717     }
4718   )";
4719   runDataflow(
4720       Code,
4721       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4722          ASTContext &ASTCtx) {
4723         ASSERT_THAT(Results.keys(),
4724                     UnorderedElementsAre("loop_body", "after_loop"));
4725         const Environment &LoopBodyEnv =
4726             getEnvironmentAtAnnotation(Results, "loop_body");
4727         const Environment &AfterLoopEnv =
4728             getEnvironmentAtAnnotation(Results, "after_loop");
4729         auto &A = AfterLoopEnv.arena();
4730 
4731         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4732         ASSERT_THAT(FooDecl, NotNull());
4733 
4734         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4735         ASSERT_THAT(BarDecl, NotNull());
4736 
4737         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4738         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
4739         EXPECT_TRUE(
4740             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4741 
4742         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4743         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
4744         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
4745         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
4746       });
4747 }
4748 
4749 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4750   std::string Code = R"(
4751     void target(bool Foo) {
4752       for (; Foo;) {
4753         (void)0;
4754         // [[loop_body]]
4755       }
4756       (void)0;
4757       // [[after_loop]]
4758     }
4759   )";
4760   runDataflow(
4761       Code,
4762       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4763          ASTContext &ASTCtx) {
4764         ASSERT_THAT(Results.keys(),
4765                     UnorderedElementsAre("loop_body", "after_loop"));
4766         const Environment &LoopBodyEnv =
4767             getEnvironmentAtAnnotation(Results, "loop_body");
4768         const Environment &AfterLoopEnv =
4769             getEnvironmentAtAnnotation(Results, "after_loop");
4770 
4771         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4772         ASSERT_THAT(FooDecl, NotNull());
4773 
4774         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4775         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4776 
4777         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4778         EXPECT_TRUE(
4779             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4780       });
4781 }
4782 
4783 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4784   std::string Code = R"(
4785     void target(bool Foo) {
4786       for (;;) {
4787         (void)0;
4788         // [[loop_body]]
4789       }
4790     }
4791   )";
4792   runDataflow(
4793       Code,
4794       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4795          ASTContext &ASTCtx) {
4796         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4797         const Environment &LoopBodyEnv =
4798             getEnvironmentAtAnnotation(Results, "loop_body");
4799 
4800         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4801         ASSERT_THAT(FooDecl, NotNull());
4802 
4803         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4804         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
4805       });
4806 }
4807 
4808 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4809   std::string Code = R"(
4810     bool GiveBool();
4811     void SetBool(bool &Var) { Var = true; }
4812 
4813     void target() {
4814       bool Foo = GiveBool();
4815       SetBool(Foo);
4816       // [[p]]
4817     }
4818   )";
4819   runDataflow(
4820       Code,
4821       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4822          ASTContext &ASTCtx) {
4823         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4824         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4825 
4826         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4827         ASSERT_THAT(FooDecl, NotNull());
4828 
4829         auto &FooVal = getFormula(*FooDecl, Env);
4830         EXPECT_FALSE(Env.proves(FooVal));
4831         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
4832       },
4833       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4834 }
4835 
4836 TEST(TransferTest, ContextSensitiveReturnReference) {
4837   std::string Code = R"(
4838     class S {};
4839     S& target(bool b, S &s) {
4840       return s;
4841       // [[p]]
4842     }
4843   )";
4844   runDataflow(
4845       Code,
4846       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4847          ASTContext &ASTCtx) {
4848         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4849 
4850         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4851         ASSERT_THAT(SDecl, NotNull());
4852 
4853         auto *SLoc = Env.getStorageLocation(*SDecl);
4854         ASSERT_THAT(SLoc, NotNull());
4855 
4856         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4857       },
4858       {BuiltinOptions{ContextSensitiveOptions{}}});
4859 }
4860 
4861 // This test is a regression test, based on a real crash.
4862 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4863   std::string Code = R"(
4864     class S {};
4865     S& target(bool b, S &s) {
4866       return b ? s : s;
4867       // [[p]]
4868     }
4869   )";
4870   runDataflow(
4871       Code,
4872       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4873          ASTContext &ASTCtx) {
4874         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4875         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4876 
4877         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4878         ASSERT_THAT(SDecl, NotNull());
4879 
4880         auto *SLoc = Env.getStorageLocation(*SDecl);
4881         ASSERT_THAT(SLoc, NotNull());
4882         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4883 
4884         auto *Loc = Env.getReturnStorageLocation();
4885         ASSERT_THAT(Loc, NotNull());
4886         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4887 
4888         // TODO: We would really like to make this stronger assertion, but that
4889         // doesn't work because we don't propagate values correctly through
4890         // the conditional operator yet.
4891         // ASSERT_THAT(Loc, Eq(SLoc));
4892       },
4893       {BuiltinOptions{ContextSensitiveOptions{}}});
4894 }
4895 
4896 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4897   std::string Code = R"(
4898     class S {};
4899     S &callee(bool b, S &s1_parm, S &s2_parm) {
4900       if (b)
4901         return s1_parm;
4902       else
4903         return s2_parm;
4904     }
4905     void target(bool b) {
4906       S s1;
4907       S s2;
4908       S &return_s1 = s1;
4909       S &return_s2 = s2;
4910       S &return_dont_know = callee(b, s1, s2);
4911       // [[p]]
4912     }
4913   )";
4914   runDataflow(
4915       Code,
4916       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4917          ASTContext &ASTCtx) {
4918         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4919 
4920         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4921         ASSERT_THAT(S1, NotNull());
4922         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4923         ASSERT_THAT(S2, NotNull());
4924         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4925         ASSERT_THAT(ReturnS1, NotNull());
4926         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4927         ASSERT_THAT(ReturnS2, NotNull());
4928         const ValueDecl *ReturnDontKnow =
4929             findValueDecl(ASTCtx, "return_dont_know");
4930         ASSERT_THAT(ReturnDontKnow, NotNull());
4931 
4932         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4933         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4934 
4935         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4936         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4937 
4938         // In the case where we don't have a consistent storage location for
4939         // the return value, the framework creates a new storage location, which
4940         // should be different from the storage locations of `s1` and `s2`.
4941         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4942         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4943       },
4944       {BuiltinOptions{ContextSensitiveOptions{}}});
4945 }
4946 
4947 TEST(TransferTest, ContextSensitiveDepthZero) {
4948   std::string Code = R"(
4949     bool GiveBool();
4950     void SetBool(bool &Var) { Var = true; }
4951 
4952     void target() {
4953       bool Foo = GiveBool();
4954       SetBool(Foo);
4955       // [[p]]
4956     }
4957   )";
4958   runDataflow(
4959       Code,
4960       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4961          ASTContext &ASTCtx) {
4962         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4963         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4964 
4965         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4966         ASSERT_THAT(FooDecl, NotNull());
4967 
4968         auto &FooVal = getFormula(*FooDecl, Env);
4969         EXPECT_FALSE(Env.proves(FooVal));
4970         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
4971       },
4972       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4973 }
4974 
4975 TEST(TransferTest, ContextSensitiveSetTrue) {
4976   std::string Code = R"(
4977     bool GiveBool();
4978     void SetBool(bool &Var) { Var = true; }
4979 
4980     void target() {
4981       bool Foo = GiveBool();
4982       SetBool(Foo);
4983       // [[p]]
4984     }
4985   )";
4986   runDataflow(
4987       Code,
4988       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4989          ASTContext &ASTCtx) {
4990         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4991         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4992 
4993         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4994         ASSERT_THAT(FooDecl, NotNull());
4995 
4996         auto &FooVal = getFormula(*FooDecl, Env);
4997         EXPECT_TRUE(Env.proves(FooVal));
4998       },
4999       {BuiltinOptions{ContextSensitiveOptions{}}});
5000 }
5001 
5002 TEST(TransferTest, ContextSensitiveSetFalse) {
5003   std::string Code = R"(
5004     bool GiveBool();
5005     void SetBool(bool &Var) { Var = false; }
5006 
5007     void target() {
5008       bool Foo = GiveBool();
5009       SetBool(Foo);
5010       // [[p]]
5011     }
5012   )";
5013   runDataflow(
5014       Code,
5015       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5016          ASTContext &ASTCtx) {
5017         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5018         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5019 
5020         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5021         ASSERT_THAT(FooDecl, NotNull());
5022 
5023         auto &FooVal = getFormula(*FooDecl, Env);
5024         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5025       },
5026       {BuiltinOptions{ContextSensitiveOptions{}}});
5027 }
5028 
5029 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5030   std::string Code = R"(
5031     bool GiveBool();
5032     void SetBool(bool &Var, bool Val) { Var = Val; }
5033 
5034     void target() {
5035       bool Foo = GiveBool();
5036       bool Bar = GiveBool();
5037       SetBool(Foo, true);
5038       SetBool(Bar, false);
5039       // [[p]]
5040     }
5041   )";
5042   runDataflow(
5043       Code,
5044       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5045          ASTContext &ASTCtx) {
5046         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5047         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5048         auto &A = Env.arena();
5049 
5050         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5051         ASSERT_THAT(FooDecl, NotNull());
5052 
5053         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5054         ASSERT_THAT(BarDecl, NotNull());
5055 
5056         auto &FooVal = getFormula(*FooDecl, Env);
5057         EXPECT_TRUE(Env.proves(FooVal));
5058         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
5059 
5060         auto &BarVal = getFormula(*BarDecl, Env);
5061         EXPECT_FALSE(Env.proves(BarVal));
5062         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
5063       },
5064       {BuiltinOptions{ContextSensitiveOptions{}}});
5065 }
5066 
5067 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
5068   std::string Code = R"(
5069     bool GiveBool();
5070     void SetBool1(bool &Var) { Var = true; }
5071     void SetBool2(bool &Var) { SetBool1(Var); }
5072 
5073     void target() {
5074       bool Foo = GiveBool();
5075       SetBool2(Foo);
5076       // [[p]]
5077     }
5078   )";
5079   runDataflow(
5080       Code,
5081       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5082          ASTContext &ASTCtx) {
5083         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5084         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5085 
5086         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5087         ASSERT_THAT(FooDecl, NotNull());
5088 
5089         auto &FooVal = getFormula(*FooDecl, Env);
5090         EXPECT_FALSE(Env.proves(FooVal));
5091         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5092       },
5093       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5094 }
5095 
5096 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5097   std::string Code = R"(
5098     bool GiveBool();
5099     void SetBool1(bool &Var) { Var = true; }
5100     void SetBool2(bool &Var) { SetBool1(Var); }
5101 
5102     void target() {
5103       bool Foo = GiveBool();
5104       SetBool2(Foo);
5105       // [[p]]
5106     }
5107   )";
5108   runDataflow(
5109       Code,
5110       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5111          ASTContext &ASTCtx) {
5112         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5113         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5114 
5115         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5116         ASSERT_THAT(FooDecl, NotNull());
5117 
5118         auto &FooVal = getFormula(*FooDecl, Env);
5119         EXPECT_TRUE(Env.proves(FooVal));
5120       },
5121       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5122 }
5123 
5124 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5125   std::string Code = R"(
5126     bool GiveBool();
5127     void SetBool1(bool &Var) { Var = true; }
5128     void SetBool2(bool &Var) { SetBool1(Var); }
5129     void SetBool3(bool &Var) { SetBool2(Var); }
5130 
5131     void target() {
5132       bool Foo = GiveBool();
5133       SetBool3(Foo);
5134       // [[p]]
5135     }
5136   )";
5137   runDataflow(
5138       Code,
5139       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5140          ASTContext &ASTCtx) {
5141         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5142         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5143 
5144         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5145         ASSERT_THAT(FooDecl, NotNull());
5146 
5147         auto &FooVal = getFormula(*FooDecl, Env);
5148         EXPECT_FALSE(Env.proves(FooVal));
5149         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5150       },
5151       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5152 }
5153 
5154 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5155   std::string Code = R"(
5156     bool GiveBool();
5157     void SetBool1(bool &Var) { Var = true; }
5158     void SetBool2(bool &Var) { SetBool1(Var); }
5159     void SetBool3(bool &Var) { SetBool2(Var); }
5160 
5161     void target() {
5162       bool Foo = GiveBool();
5163       SetBool3(Foo);
5164       // [[p]]
5165     }
5166   )";
5167   runDataflow(
5168       Code,
5169       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5170          ASTContext &ASTCtx) {
5171         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5172         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5173 
5174         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5175         ASSERT_THAT(FooDecl, NotNull());
5176 
5177         auto &FooVal = getFormula(*FooDecl, Env);
5178         EXPECT_TRUE(Env.proves(FooVal));
5179       },
5180       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5181 }
5182 
5183 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5184   std::string Code = R"(
5185     bool Pong(bool X, bool Y);
5186 
5187     bool Ping(bool X, bool Y) {
5188       if (X) {
5189         return Y;
5190       } else {
5191         return Pong(!X, Y);
5192       }
5193     }
5194 
5195     bool Pong(bool X, bool Y) {
5196       if (Y) {
5197         return X;
5198       } else {
5199         return Ping(X, !Y);
5200       }
5201     }
5202 
5203     void target() {
5204       bool Foo = Ping(false, false);
5205       // [[p]]
5206     }
5207   )";
5208   runDataflow(
5209       Code,
5210       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5211          ASTContext &ASTCtx) {
5212         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5213         // The analysis doesn't crash...
5214         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5215 
5216         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5217         ASSERT_THAT(FooDecl, NotNull());
5218 
5219         auto &FooVal = getFormula(*FooDecl, Env);
5220         // ... but it also can't prove anything here.
5221         EXPECT_FALSE(Env.proves(FooVal));
5222         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5223       },
5224       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5225 }
5226 
5227 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5228   std::string Code = R"(
5229     void SetBools(bool &Var1, bool &Var2) {
5230       Var1 = true;
5231       Var2 = false;
5232     }
5233 
5234     void target() {
5235       bool Foo = false;
5236       bool Bar = true;
5237       SetBools(Foo, Bar);
5238       // [[p]]
5239     }
5240   )";
5241   runDataflow(
5242       Code,
5243       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5244          ASTContext &ASTCtx) {
5245         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5246         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5247 
5248         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5249         ASSERT_THAT(FooDecl, NotNull());
5250 
5251         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5252         ASSERT_THAT(BarDecl, NotNull());
5253 
5254         auto &FooVal = getFormula(*FooDecl, Env);
5255         EXPECT_TRUE(Env.proves(FooVal));
5256         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5257 
5258         auto &BarVal = getFormula(*BarDecl, Env);
5259         EXPECT_FALSE(Env.proves(BarVal));
5260         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5261       },
5262       {BuiltinOptions{ContextSensitiveOptions{}}});
5263 }
5264 
5265 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5266   std::string Code = R"(
5267     void IfCond(bool Cond, bool &Then, bool &Else) {
5268       if (Cond) {
5269         Then = true;
5270       } else {
5271         Else = true;
5272       }
5273     }
5274 
5275     void target() {
5276       bool Foo = false;
5277       bool Bar = false;
5278       bool Baz = false;
5279       IfCond(Foo, Bar, Baz);
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 *BarDecl = findValueDecl(ASTCtx, "Bar");
5291         ASSERT_THAT(BarDecl, NotNull());
5292 
5293         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5294         ASSERT_THAT(BazDecl, NotNull());
5295 
5296         auto &BarVal = getFormula(*BarDecl, Env);
5297         EXPECT_FALSE(Env.proves(BarVal));
5298         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5299 
5300         auto &BazVal = getFormula(*BazDecl, Env);
5301         EXPECT_TRUE(Env.proves(BazVal));
5302         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5303       },
5304       {BuiltinOptions{ContextSensitiveOptions{}}});
5305 }
5306 
5307 TEST(TransferTest, ContextSensitiveReturnVoid) {
5308   std::string Code = R"(
5309     void Noop() { return; }
5310 
5311     void target() {
5312       Noop();
5313       // [[p]]
5314     }
5315   )";
5316   runDataflow(
5317       Code,
5318       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5319          ASTContext &ASTCtx) {
5320         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5321         // This just tests that the analysis doesn't crash.
5322       },
5323       {BuiltinOptions{ContextSensitiveOptions{}}});
5324 }
5325 
5326 TEST(TransferTest, ContextSensitiveReturnTrue) {
5327   std::string Code = R"(
5328     bool GiveBool() { return true; }
5329 
5330     void target() {
5331       bool Foo = GiveBool();
5332       // [[p]]
5333     }
5334   )";
5335   runDataflow(
5336       Code,
5337       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5338          ASTContext &ASTCtx) {
5339         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5340         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5341 
5342         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5343         ASSERT_THAT(FooDecl, NotNull());
5344 
5345         auto &FooVal = getFormula(*FooDecl, Env);
5346         EXPECT_TRUE(Env.proves(FooVal));
5347       },
5348       {BuiltinOptions{ContextSensitiveOptions{}}});
5349 }
5350 
5351 TEST(TransferTest, ContextSensitiveReturnFalse) {
5352   std::string Code = R"(
5353     bool GiveBool() { return false; }
5354 
5355     void target() {
5356       bool Foo = GiveBool();
5357       // [[p]]
5358     }
5359   )";
5360   runDataflow(
5361       Code,
5362       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5363          ASTContext &ASTCtx) {
5364         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5365         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5366 
5367         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5368         ASSERT_THAT(FooDecl, NotNull());
5369 
5370         auto &FooVal = getFormula(*FooDecl, Env);
5371         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5372       },
5373       {BuiltinOptions{ContextSensitiveOptions{}}});
5374 }
5375 
5376 TEST(TransferTest, ContextSensitiveReturnArg) {
5377   std::string Code = R"(
5378     bool GiveBool();
5379     bool GiveBack(bool Arg) { return Arg; }
5380 
5381     void target() {
5382       bool Foo = GiveBool();
5383       bool Bar = GiveBack(Foo);
5384       bool Baz = Foo == Bar;
5385       // [[p]]
5386     }
5387   )";
5388   runDataflow(
5389       Code,
5390       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5391          ASTContext &ASTCtx) {
5392         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5393         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5394 
5395         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5396         ASSERT_THAT(BazDecl, NotNull());
5397 
5398         auto &BazVal = getFormula(*BazDecl, Env);
5399         EXPECT_TRUE(Env.proves(BazVal));
5400       },
5401       {BuiltinOptions{ContextSensitiveOptions{}}});
5402 }
5403 
5404 TEST(TransferTest, ContextSensitiveReturnInt) {
5405   std::string Code = R"(
5406     int identity(int x) { return x; }
5407 
5408     void target() {
5409       int y = identity(42);
5410       // [[p]]
5411     }
5412   )";
5413   runDataflow(
5414       Code,
5415       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5416          ASTContext &ASTCtx) {
5417         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5418         // This just tests that the analysis doesn't crash.
5419       },
5420       {BuiltinOptions{ContextSensitiveOptions{}}});
5421 }
5422 
5423 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5424   std::string Code = R"(
5425     class MyClass {
5426     public:
5427       bool giveBool() { return true; }
5428     };
5429 
5430     void target() {
5431       MyClass MyObj;
5432       bool Foo = MyObj.giveBool();
5433       // [[p]]
5434     }
5435   )";
5436   runDataflow(
5437       Code,
5438       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5439          ASTContext &ASTCtx) {
5440         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5441         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5442 
5443         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5444         ASSERT_THAT(FooDecl, NotNull());
5445 
5446         auto &FooVal = getFormula(*FooDecl, Env);
5447         EXPECT_TRUE(Env.proves(FooVal));
5448       },
5449       {BuiltinOptions{ContextSensitiveOptions{}}});
5450 }
5451 
5452 TEST(TransferTest, ContextSensitiveMethodGetter) {
5453   std::string Code = R"(
5454     class MyClass {
5455     public:
5456       bool getField() { return Field; }
5457 
5458       bool Field;
5459     };
5460 
5461     void target() {
5462       MyClass MyObj;
5463       MyObj.Field = true;
5464       bool Foo = MyObj.getField();
5465       // [[p]]
5466     }
5467   )";
5468   runDataflow(
5469       Code,
5470       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5471          ASTContext &ASTCtx) {
5472         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5473         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5474 
5475         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5476         ASSERT_THAT(FooDecl, NotNull());
5477 
5478         auto &FooVal = getFormula(*FooDecl, Env);
5479         EXPECT_TRUE(Env.proves(FooVal));
5480       },
5481       {BuiltinOptions{ContextSensitiveOptions{}}});
5482 }
5483 
5484 TEST(TransferTest, ContextSensitiveMethodSetter) {
5485   std::string Code = R"(
5486     class MyClass {
5487     public:
5488       void setField(bool Val) { Field = Val; }
5489 
5490       bool Field;
5491     };
5492 
5493     void target() {
5494       MyClass MyObj;
5495       MyObj.setField(true);
5496       bool Foo = MyObj.Field;
5497       // [[p]]
5498     }
5499   )";
5500   runDataflow(
5501       Code,
5502       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5503          ASTContext &ASTCtx) {
5504         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5505         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5506 
5507         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5508         ASSERT_THAT(FooDecl, NotNull());
5509 
5510         auto &FooVal = getFormula(*FooDecl, Env);
5511         EXPECT_TRUE(Env.proves(FooVal));
5512       },
5513       {BuiltinOptions{ContextSensitiveOptions{}}});
5514 }
5515 
5516 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5517   std::string Code = R"(
5518     class MyClass {
5519     public:
5520       bool getField() { return Field; }
5521       void setField(bool Val) { Field = Val; }
5522 
5523     private:
5524       bool Field;
5525     };
5526 
5527     void target() {
5528       MyClass MyObj;
5529       MyObj.setField(true);
5530       bool Foo = MyObj.getField();
5531       // [[p]]
5532     }
5533   )";
5534   runDataflow(
5535       Code,
5536       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5537          ASTContext &ASTCtx) {
5538         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5539         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5540 
5541         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5542         ASSERT_THAT(FooDecl, NotNull());
5543 
5544         auto &FooVal = getFormula(*FooDecl, Env);
5545         EXPECT_TRUE(Env.proves(FooVal));
5546       },
5547       {BuiltinOptions{ContextSensitiveOptions{}}});
5548 }
5549 
5550 
5551 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5552   std::string Code = R"(
5553     class MyClass {
5554     public:
5555       void Inner() { MyField = true; }
5556       void Outer() { Inner(); }
5557 
5558       bool MyField;
5559     };
5560 
5561     void target() {
5562       MyClass MyObj;
5563       MyObj.Outer();
5564       bool Foo = MyObj.MyField;
5565       // [[p]]
5566     }
5567   )";
5568   runDataflow(
5569       Code,
5570       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5571          ASTContext &ASTCtx) {
5572         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5573         ;
5574         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5575 
5576         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5577         ASSERT_THAT(FooDecl, NotNull());
5578 
5579         auto &FooVal = getFormula(*FooDecl, Env);
5580         EXPECT_TRUE(Env.proves(FooVal));
5581       },
5582       {BuiltinOptions{ContextSensitiveOptions{}}});
5583 }
5584 
5585 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5586   std::string Code = R"(
5587     class MyClass {
5588     public:
5589       bool Inner() { return MyField; }
5590       bool Outer() { return Inner(); }
5591 
5592       bool MyField;
5593     };
5594 
5595     void target() {
5596       MyClass MyObj;
5597       MyObj.MyField = true;
5598       bool Foo = MyObj.Outer();
5599       // [[p]]
5600     }
5601   )";
5602   runDataflow(
5603       Code,
5604       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5605          ASTContext &ASTCtx) {
5606         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5607         ;
5608         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5609 
5610         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5611         ASSERT_THAT(FooDecl, NotNull());
5612 
5613         auto &FooVal = getFormula(*FooDecl, Env);
5614         EXPECT_TRUE(Env.proves(FooVal));
5615       },
5616       {BuiltinOptions{ContextSensitiveOptions{}}});
5617 }
5618 
5619 TEST(TransferTest, ContextSensitiveConstructorBody) {
5620   std::string Code = R"(
5621     class MyClass {
5622     public:
5623       MyClass() { MyField = true; }
5624 
5625       bool MyField;
5626     };
5627 
5628     void target() {
5629       MyClass MyObj;
5630       bool Foo = MyObj.MyField;
5631       // [[p]]
5632     }
5633   )";
5634   runDataflow(
5635       Code,
5636       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5637          ASTContext &ASTCtx) {
5638         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5639         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5640 
5641         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5642         ASSERT_THAT(FooDecl, NotNull());
5643 
5644         auto &FooVal = getFormula(*FooDecl, Env);
5645         EXPECT_TRUE(Env.proves(FooVal));
5646       },
5647       {BuiltinOptions{ContextSensitiveOptions{}}});
5648 }
5649 
5650 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5651   std::string Code = R"(
5652     class MyClass {
5653     public:
5654       MyClass() : MyField(true) {}
5655 
5656       bool MyField;
5657     };
5658 
5659     void target() {
5660       MyClass MyObj;
5661       bool Foo = MyObj.MyField;
5662       // [[p]]
5663     }
5664   )";
5665   runDataflow(
5666       Code,
5667       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5668          ASTContext &ASTCtx) {
5669         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5670         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5671 
5672         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5673         ASSERT_THAT(FooDecl, NotNull());
5674 
5675         auto &FooVal = getFormula(*FooDecl, Env);
5676         EXPECT_TRUE(Env.proves(FooVal));
5677       },
5678       {BuiltinOptions{ContextSensitiveOptions{}}});
5679 }
5680 
5681 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5682   std::string Code = R"(
5683     class MyClass {
5684     public:
5685       MyClass() = default;
5686 
5687       bool MyField = true;
5688     };
5689 
5690     void target() {
5691       MyClass MyObj;
5692       bool Foo = MyObj.MyField;
5693       // [[p]]
5694     }
5695   )";
5696   runDataflow(
5697       Code,
5698       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5699          ASTContext &ASTCtx) {
5700         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5701         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5702 
5703         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5704         ASSERT_THAT(FooDecl, NotNull());
5705 
5706         auto &FooVal = getFormula(*FooDecl, Env);
5707         EXPECT_TRUE(Env.proves(FooVal));
5708       },
5709       {BuiltinOptions{ContextSensitiveOptions{}}});
5710 }
5711 
5712 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
5713   // Test that the `this` pointer seen in the constructor has the same value
5714   // as the address of the variable the object is constructed into.
5715   std::string Code = R"(
5716     class MyClass {
5717     public:
5718       MyClass() : Self(this) {}
5719       MyClass *Self;
5720     };
5721 
5722     void target() {
5723       MyClass MyObj;
5724       MyClass *SelfPtr = MyObj.Self;
5725       // [[p]]
5726     }
5727   )";
5728   runDataflow(
5729       Code,
5730       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5731          ASTContext &ASTCtx) {
5732         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5733 
5734         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
5735         ASSERT_THAT(MyObjDecl, NotNull());
5736 
5737         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
5738         ASSERT_THAT(SelfDecl, NotNull());
5739 
5740         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5741         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
5742         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
5743       },
5744       {BuiltinOptions{ContextSensitiveOptions{}}});
5745 }
5746 
5747 TEST(TransferTest, UnnamedBitfieldInitializer) {
5748   std::string Code = R"(
5749     struct B {};
5750     struct A {
5751       unsigned a;
5752       unsigned : 4;
5753       unsigned c;
5754       B b;
5755     };
5756     void target() {
5757       A a = {};
5758       A test = a;
5759       (void)test.c;
5760     }
5761   )";
5762   runDataflow(
5763       Code,
5764       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5765          ASTContext &ASTCtx) {
5766         // This doesn't need a body because this test was crashing the framework
5767         // before handling correctly Unnamed bitfields in `InitListExpr`.
5768       });
5769 }
5770 
5771 // Repro for a crash that used to occur with chained short-circuiting logical
5772 // operators.
5773 TEST(TransferTest, ChainedLogicalOps) {
5774   std::string Code = R"(
5775     bool target() {
5776       bool b = true || false || false || false;
5777       // [[p]]
5778       return b;
5779     }
5780   )";
5781   runDataflow(
5782       Code,
5783       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5784          ASTContext &ASTCtx) {
5785         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5786         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
5787         EXPECT_TRUE(Env.proves(B));
5788       });
5789 }
5790 
5791 // Repro for a crash that used to occur when we call a `noreturn` function
5792 // within one of the operands of a `&&` or `||` operator.
5793 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5794   std::string Code = R"(
5795     __attribute__((noreturn)) int doesnt_return();
5796     bool some_condition();
5797     void target(bool b1, bool b2) {
5798       // Neither of these should crash. In addition, if we don't terminate the
5799       // program, we know that the operators need to trigger the short-circuit
5800       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5801       // will be true.
5802       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5803       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5804 
5805       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5806       // entire expression unreachable. So we know that in both of the following
5807       // cases, if `target()` terminates, the `else` branch was taken.
5808       bool NoreturnOnLhsMakesAndUnreachable = false;
5809       if (some_condition())
5810          doesnt_return() > 0 && some_condition();
5811       else
5812          NoreturnOnLhsMakesAndUnreachable = true;
5813 
5814       bool NoreturnOnLhsMakesOrUnreachable = false;
5815       if (some_condition())
5816          doesnt_return() > 0 || some_condition();
5817       else
5818          NoreturnOnLhsMakesOrUnreachable = true;
5819 
5820       // [[p]]
5821     }
5822   )";
5823   runDataflow(
5824       Code,
5825       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5826          ASTContext &ASTCtx) {
5827         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5828         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5829         auto &A = Env.arena();
5830 
5831         // Check that [[p]] is reachable with a non-false flow condition.
5832         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
5833 
5834         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
5835         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
5836 
5837         auto &NoreturnOnRhsOfAnd =
5838             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
5839         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
5840 
5841         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
5842         EXPECT_TRUE(Env.proves(B2));
5843 
5844         auto &NoreturnOnRhsOfOr =
5845             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
5846                 .formula();
5847         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
5848 
5849         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5850             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
5851         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
5852 
5853         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5854             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
5855         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
5856       });
5857 }
5858 
5859 TEST(TransferTest, NewExpressions) {
5860   std::string Code = R"(
5861     void target() {
5862       int *p = new int(42);
5863       // [[after_new]]
5864     }
5865   )";
5866   runDataflow(
5867       Code,
5868       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5869          ASTContext &ASTCtx) {
5870         const Environment &Env =
5871             getEnvironmentAtAnnotation(Results, "after_new");
5872 
5873         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5874 
5875         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5876       });
5877 }
5878 
5879 TEST(TransferTest, NewExpressions_Structs) {
5880   std::string Code = R"(
5881     struct Inner {
5882       int InnerField;
5883     };
5884 
5885     struct Outer {
5886       Inner OuterField;
5887     };
5888 
5889     void target() {
5890       Outer *p = new Outer;
5891       // Access the fields to make sure the analysis actually generates children
5892       // for them in the `RecordStorageLocation` and `RecordValue`.
5893       p->OuterField.InnerField;
5894       // [[after_new]]
5895     }
5896   )";
5897   runDataflow(
5898       Code,
5899       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5900          ASTContext &ASTCtx) {
5901         const Environment &Env =
5902             getEnvironmentAtAnnotation(Results, "after_new");
5903 
5904         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5905         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5906 
5907         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5908 
5909         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
5910         auto &OuterFieldLoc =
5911             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
5912         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
5913 
5914         // Values for the struct and all fields exist after the new.
5915         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5916         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5917         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5918       });
5919 }
5920 
5921 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5922   std::string Code = R"(
5923     struct A { static void static_member_func(); };
5924     void target() {
5925       // To check that we're treating function-to-pointer decay correctly,
5926       // create two pointers, then verify they refer to the same storage
5927       // location.
5928       // We need to do the test this way because even if an initializer (in this
5929       // case, the function-to-pointer decay) does not create a value, we still
5930       // create a value for the variable.
5931       void (*non_member_p1)() = target;
5932       void (*non_member_p2)() = target;
5933 
5934       // Do the same thing but for a static member function.
5935       void (*member_p1)() = A::static_member_func;
5936       void (*member_p2)() = A::static_member_func;
5937       // [[p]]
5938     }
5939   )";
5940   runDataflow(
5941       Code,
5942       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5943          ASTContext &ASTCtx) {
5944         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5945 
5946         auto &NonMemberP1 =
5947             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
5948         auto &NonMemberP2 =
5949             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
5950         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
5951 
5952         auto &MemberP1 =
5953             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
5954         auto &MemberP2 =
5955             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
5956         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
5957       });
5958 }
5959 
5960 // Check that a builtin function is not associated with a value. (It's only
5961 // possible to call builtin functions directly, not take their address.)
5962 TEST(TransferTest, BuiltinFunctionModeled) {
5963   std::string Code = R"(
5964     void target() {
5965       __builtin_expect(0, 0);
5966       // [[p]]
5967     }
5968   )";
5969   runDataflow(
5970       Code,
5971       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5972          ASTContext &ASTCtx) {
5973         using ast_matchers::selectFirst;
5974         using ast_matchers::match;
5975         using ast_matchers::traverse;
5976         using ast_matchers::implicitCastExpr;
5977         using ast_matchers::hasCastKind;
5978 
5979         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5980 
5981         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
5982             "implicit_cast",
5983             match(traverse(TK_AsIs,
5984                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
5985                                .bind("implicit_cast")),
5986                   ASTCtx));
5987 
5988         ASSERT_THAT(ImplicitCast, NotNull());
5989         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
5990       });
5991 }
5992 
5993 // Check that a callee of a member operator call is modeled as a `PointerValue`.
5994 // Member operator calls are unusual in that their callee is a pointer that
5995 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
5996 // member functions, the callee is a `MemberExpr` (which does not have pointer
5997 // type).
5998 // We want to make sure that we produce a pointer value for the callee in this
5999 // specific scenario and that its storage location is durable (for convergence).
6000 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
6001   std::string Code = R"(
6002     struct S {
6003       bool operator!=(S s);
6004     };
6005     void target() {
6006       S s;
6007       (void)(s != s);
6008       (void)(s != s);
6009       // [[p]]
6010     }
6011   )";
6012   runDataflow(
6013       Code,
6014       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6015          ASTContext &ASTCtx) {
6016         using ast_matchers::selectFirst;
6017         using ast_matchers::match;
6018         using ast_matchers::traverse;
6019         using ast_matchers::cxxOperatorCallExpr;
6020 
6021         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6022 
6023         auto Matches = match(
6024             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
6025 
6026         ASSERT_EQ(Matches.size(), 2UL);
6027 
6028         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
6029         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
6030 
6031         ASSERT_THAT(Call1, NotNull());
6032         ASSERT_THAT(Call2, NotNull());
6033 
6034         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
6035                   CK_FunctionToPointerDecay);
6036         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
6037                   CK_FunctionToPointerDecay);
6038 
6039         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
6040         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
6041 
6042         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
6043       });
6044 }
6045 
6046 // Check that fields of anonymous records are modeled.
6047 TEST(TransferTest, AnonymousStruct) {
6048   std::string Code = R"(
6049     struct S {
6050       struct {
6051         bool b;
6052       };
6053     };
6054     void target() {
6055       S s;
6056       s.b = true;
6057       // [[p]]
6058     }
6059   )";
6060   runDataflow(
6061       Code,
6062       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6063          ASTContext &ASTCtx) {
6064         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6065         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
6066         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6067         const IndirectFieldDecl *IndirectField =
6068             findIndirectFieldDecl(ASTCtx, "b");
6069 
6070         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
6071         auto &AnonStruct = *cast<RecordStorageLocation>(
6072             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
6073 
6074         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6075         ASSERT_TRUE(Env.proves(B->formula()));
6076       });
6077 }
6078 
6079 TEST(TransferTest, AnonymousStructWithInitializer) {
6080   std::string Code = R"(
6081     struct target {
6082       target() {
6083         (void)0;
6084         // [[p]]
6085       }
6086       struct {
6087         bool b = true;
6088       };
6089     };
6090   )";
6091   runDataflow(
6092       Code,
6093       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6094          ASTContext &ASTCtx) {
6095         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6096         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6097         const IndirectFieldDecl *IndirectField =
6098             findIndirectFieldDecl(ASTCtx, "b");
6099 
6100         auto *ThisLoc =
6101             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6102         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6103             *cast<ValueDecl>(IndirectField->chain().front())));
6104 
6105         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6106         ASSERT_TRUE(Env.proves(B->formula()));
6107       });
6108 }
6109 
6110 TEST(TransferTest, AnonymousStructWithReferenceField) {
6111   std::string Code = R"(
6112     int global_i = 0;
6113     struct target {
6114       target() {
6115         (void)0;
6116         // [[p]]
6117       }
6118       struct {
6119         int &i = global_i;
6120       };
6121     };
6122   )";
6123   runDataflow(
6124       Code,
6125       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6126          ASTContext &ASTCtx) {
6127         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6128         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6129         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6130         const IndirectFieldDecl *IndirectField =
6131             findIndirectFieldDecl(ASTCtx, "i");
6132 
6133         auto *ThisLoc =
6134             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6135         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6136             *cast<ValueDecl>(IndirectField->chain().front())));
6137 
6138         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6139                   Env.getStorageLocation(*GlobalIDecl));
6140       });
6141 }
6142 
6143 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6144   // This is a crash repro.
6145   // `false` block may not have been processed when we try to evaluate the `||`
6146   // after visiting `true`, because it is not necessary (and therefore the edge
6147   // is marked unreachable). Trying to get the analysis state via
6148   // `getEnvironment` for the subexpression still should not crash.
6149   std::string Code = R"(
6150     int target(int i) {
6151       if ((i < 0 && true) || false) {
6152         return 0;
6153       }
6154       return 0;
6155     }
6156   )";
6157   runDataflow(
6158       Code,
6159       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6160          ASTContext &ASTCtx) {});
6161 }
6162 
6163 TEST(TransferTest, LambdaCaptureByCopy) {
6164   std::string Code = R"(
6165     void target(int Foo, int Bar) {
6166       [Foo]() {
6167         (void)0;
6168         // [[p]]
6169       }();
6170     }
6171   )";
6172   runDataflowOnLambda(
6173       Code,
6174       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6175          ASTContext &ASTCtx) {
6176         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6177         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6178 
6179         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6180         ASSERT_THAT(FooDecl, NotNull());
6181 
6182         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6183         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6184 
6185         const Value *FooVal = Env.getValue(*FooLoc);
6186         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6187 
6188         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6189         ASSERT_THAT(BarDecl, NotNull());
6190 
6191         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6192         EXPECT_THAT(BarLoc, IsNull());
6193       });
6194 }
6195 
6196 TEST(TransferTest, LambdaCaptureByReference) {
6197   std::string Code = R"(
6198     void target(int Foo, int Bar) {
6199       [&Foo]() {
6200         (void)0;
6201         // [[p]]
6202       }();
6203     }
6204   )";
6205   runDataflowOnLambda(
6206       Code,
6207       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6208          ASTContext &ASTCtx) {
6209         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6210         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6211 
6212         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6213         ASSERT_THAT(FooDecl, NotNull());
6214 
6215         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6216         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6217 
6218         const Value *FooVal = Env.getValue(*FooLoc);
6219         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6220 
6221         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6222         ASSERT_THAT(BarDecl, NotNull());
6223 
6224         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6225         EXPECT_THAT(BarLoc, IsNull());
6226       });
6227 }
6228 
6229 TEST(TransferTest, LambdaCaptureWithInitializer) {
6230   std::string Code = R"(
6231     void target(int Bar) {
6232       [Foo=Bar]() {
6233         (void)0;
6234         // [[p]]
6235       }();
6236     }
6237   )";
6238   runDataflowOnLambda(
6239       Code,
6240       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6241          ASTContext &ASTCtx) {
6242         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6243         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6244 
6245         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6246         ASSERT_THAT(FooDecl, NotNull());
6247 
6248         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6249         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6250 
6251         const Value *FooVal = Env.getValue(*FooLoc);
6252         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6253 
6254         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6255         ASSERT_THAT(BarDecl, NotNull());
6256 
6257         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6258         EXPECT_THAT(BarLoc, IsNull());
6259       });
6260 }
6261 
6262 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
6263   std::string Code = R"(
6264     void target(int Foo, int Bar) {
6265       [=]() {
6266         Foo;
6267         // [[p]]
6268       }();
6269     }
6270   )";
6271   runDataflowOnLambda(
6272       Code,
6273       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6274          ASTContext &ASTCtx) {
6275         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6276         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6277 
6278         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6279         ASSERT_THAT(FooDecl, NotNull());
6280 
6281         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6282         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6283 
6284         const Value *FooVal = Env.getValue(*FooLoc);
6285         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6286 
6287         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6288         ASSERT_THAT(BarDecl, NotNull());
6289 
6290         // There is no storage location for `Bar` because it isn't used in the
6291         // body of the lambda.
6292         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6293         EXPECT_THAT(BarLoc, IsNull());
6294       });
6295 }
6296 
6297 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
6298   std::string Code = R"(
6299     void target(int Foo, int Bar) {
6300       [&]() {
6301         Foo;
6302         // [[p]]
6303       }();
6304     }
6305   )";
6306   runDataflowOnLambda(
6307       Code,
6308       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6309          ASTContext &ASTCtx) {
6310         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6311         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6312 
6313         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6314         ASSERT_THAT(FooDecl, NotNull());
6315 
6316         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6317         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6318 
6319         const Value *FooVal = Env.getValue(*FooLoc);
6320         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6321 
6322         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6323         ASSERT_THAT(BarDecl, NotNull());
6324 
6325         // There is no storage location for `Bar` because it isn't used in the
6326         // body of the lambda.
6327         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6328         EXPECT_THAT(BarLoc, IsNull());
6329       });
6330 }
6331 
6332 TEST(TransferTest, LambdaCaptureThis) {
6333   std::string Code = R"(
6334     struct Bar {
6335       int Foo;
6336 
6337       void target() {
6338         [this]() {
6339           Foo;
6340           // [[p]]
6341         }();
6342       }
6343     };
6344   )";
6345   runDataflowOnLambda(
6346       Code,
6347       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6348          ASTContext &ASTCtx) {
6349         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6350         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6351 
6352         const RecordStorageLocation *ThisPointeeLoc =
6353             Env.getThisPointeeStorageLocation();
6354         ASSERT_THAT(ThisPointeeLoc, NotNull());
6355 
6356         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6357         ASSERT_THAT(FooDecl, NotNull());
6358 
6359         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
6360         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6361 
6362         const Value *FooVal = Env.getValue(*FooLoc);
6363         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6364       });
6365 }
6366 
6367 TEST(TransferTest, DifferentReferenceLocInJoin) {
6368   // This test triggers a case where the storage location for a reference-type
6369   // variable is different for two states being joined. We used to believe this
6370   // could not happen and therefore had an assertion disallowing this; this test
6371   // exists to demonstrate that we can handle this condition without a failing
6372   // assertion. See also the discussion here:
6373   // https://discourse.llvm.org/t/70086/6
6374   std::string Code = R"(
6375     namespace std {
6376       template <class T> struct initializer_list {
6377         const T* begin();
6378         const T* end();
6379       };
6380     }
6381 
6382     void target(char* p, char* end) {
6383       while (p != end) {
6384         if (*p == ' ') {
6385           p++;
6386           continue;
6387         }
6388 
6389         auto && range = {1, 2};
6390         for (auto b = range.begin(), e = range.end(); b != e; ++b) {
6391         }
6392         (void)0;
6393         // [[p]]
6394       }
6395     }
6396   )";
6397   runDataflow(
6398       Code,
6399       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6400          ASTContext &ASTCtx) {
6401         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6402 
6403         // Joining environments with different storage locations for the same
6404         // declaration results in the declaration being removed from the joined
6405         // environment.
6406         const ValueDecl *VD = findValueDecl(ASTCtx, "range");
6407         ASSERT_EQ(Env.getStorageLocation(*VD), nullptr);
6408       });
6409 }
6410 
6411 } // namespace
6412