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