xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision c0703eaec1df4cde861f15e244507ef79f2d3d82)
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, ReferenceMember) {
1450   std::string Code = R"(
1451     struct A {
1452       int &Bar;
1453     };
1454 
1455     void target(A Foo) {
1456       int Baz = Foo.Bar;
1457       // [[p]]
1458     }
1459   )";
1460   runDataflow(
1461       Code,
1462       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1463          ASTContext &ASTCtx) {
1464         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1465         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1466 
1467         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1468         ASSERT_THAT(FooDecl, NotNull());
1469 
1470         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1471         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1472 
1473         FieldDecl *BarDecl = nullptr;
1474         for (FieldDecl *Field : FooFields) {
1475           if (Field->getNameAsString() == "Bar") {
1476             BarDecl = Field;
1477           } else {
1478             FAIL() << "Unexpected field: " << Field->getNameAsString();
1479           }
1480         }
1481         ASSERT_THAT(BarDecl, NotNull());
1482 
1483         const auto *FooLoc =
1484             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1485         const auto *BarReferentVal =
1486             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1487 
1488         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1489         ASSERT_THAT(BazDecl, NotNull());
1490 
1491         EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal);
1492       });
1493 }
1494 
1495 TEST(TransferTest, StructThisMember) {
1496   std::string Code = R"(
1497     struct A {
1498       int Bar;
1499 
1500       struct B {
1501         int Baz;
1502       };
1503 
1504       B Qux;
1505 
1506       void target() {
1507         int Foo = Bar;
1508         int Quux = Qux.Baz;
1509         // [[p]]
1510       }
1511     };
1512   )";
1513   runDataflow(
1514       Code,
1515       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1516          ASTContext &ASTCtx) {
1517         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1518         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1519 
1520         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1521         ASSERT_THAT(ThisLoc, NotNull());
1522 
1523         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1524         ASSERT_THAT(BarDecl, NotNull());
1525 
1526         const auto *BarLoc =
1527             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1528         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1529 
1530         const Value *BarVal = Env.getValue(*BarLoc);
1531         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1532 
1533         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1534         ASSERT_THAT(FooDecl, NotNull());
1535         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1536 
1537         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1538         ASSERT_THAT(QuxDecl, NotNull());
1539 
1540         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1541         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1542 
1543         FieldDecl *BazDecl = nullptr;
1544         for (FieldDecl *Field : QuxFields) {
1545           if (Field->getNameAsString() == "Baz") {
1546             BazDecl = Field;
1547           } else {
1548             FAIL() << "Unexpected field: " << Field->getNameAsString();
1549           }
1550         }
1551         ASSERT_THAT(BazDecl, NotNull());
1552 
1553         const auto *QuxLoc =
1554             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1555         EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
1556 
1557         const auto *BazVal =
1558             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1559 
1560         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1561         ASSERT_THAT(QuuxDecl, NotNull());
1562         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1563       });
1564 }
1565 
1566 TEST(TransferTest, ClassThisMember) {
1567   std::string Code = R"(
1568     class A {
1569       int Bar;
1570 
1571       class B {
1572       public:
1573         int Baz;
1574       };
1575 
1576       B Qux;
1577 
1578       void target() {
1579         int Foo = Bar;
1580         int Quux = Qux.Baz;
1581         // [[p]]
1582       }
1583     };
1584   )";
1585   runDataflow(
1586       Code,
1587       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1588          ASTContext &ASTCtx) {
1589         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1590         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1591 
1592         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1593 
1594         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1595         ASSERT_THAT(BarDecl, NotNull());
1596 
1597         const auto *BarLoc =
1598             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1599         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1600 
1601         const Value *BarVal = Env.getValue(*BarLoc);
1602         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1603 
1604         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1605         ASSERT_THAT(FooDecl, NotNull());
1606         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1607 
1608         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1609         ASSERT_THAT(QuxDecl, NotNull());
1610 
1611         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1612         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1613 
1614         FieldDecl *BazDecl = nullptr;
1615         for (FieldDecl *Field : QuxFields) {
1616           if (Field->getNameAsString() == "Baz") {
1617             BazDecl = Field;
1618           } else {
1619             FAIL() << "Unexpected field: " << Field->getNameAsString();
1620           }
1621         }
1622         ASSERT_THAT(BazDecl, NotNull());
1623 
1624         const auto *QuxLoc =
1625             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1626         EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
1627 
1628         const auto *BazVal =
1629             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1630 
1631         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1632         ASSERT_THAT(QuuxDecl, NotNull());
1633         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1634       });
1635 }
1636 
1637 TEST(TransferTest, UnionThisMember) {
1638   std::string Code = R"(
1639     union A {
1640       int Foo;
1641       int Bar;
1642 
1643       void target() {
1644         A a;
1645         // Mention the fields to ensure they're included in the analysis.
1646         (void)a.Foo;
1647         (void)a.Bar;
1648         // [[p]]
1649       }
1650     };
1651   )";
1652   runDataflow(
1653       Code,
1654       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1655          ASTContext &ASTCtx) {
1656         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1657         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1658 
1659         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1660         ASSERT_THAT(ThisLoc, NotNull());
1661 
1662         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1663         ASSERT_THAT(FooDecl, NotNull());
1664 
1665         const auto *FooLoc =
1666             cast<ScalarStorageLocation>(ThisLoc->getChild(*FooDecl));
1667         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1668 
1669         const Value *FooVal = Env.getValue(*FooLoc);
1670         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1671 
1672         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1673         ASSERT_THAT(BarDecl, NotNull());
1674 
1675         const auto *BarLoc =
1676             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1677         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1678 
1679         const Value *BarVal = Env.getValue(*BarLoc);
1680         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1681       });
1682 }
1683 
1684 TEST(TransferTest, StructThisInLambda) {
1685   std::string ThisCaptureCode = R"(
1686     struct A {
1687       void frob() {
1688         [this]() {
1689           int Foo = Bar;
1690           // [[p1]]
1691         }();
1692       }
1693 
1694       int Bar;
1695     };
1696   )";
1697   runDataflow(
1698       ThisCaptureCode,
1699       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1700          ASTContext &ASTCtx) {
1701         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
1702         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
1703 
1704         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1705         ASSERT_THAT(ThisLoc, NotNull());
1706 
1707         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1708         ASSERT_THAT(BarDecl, NotNull());
1709 
1710         const auto *BarLoc =
1711             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1712         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1713 
1714         const Value *BarVal = Env.getValue(*BarLoc);
1715         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1716 
1717         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1718         ASSERT_THAT(FooDecl, NotNull());
1719         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1720       },
1721       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1722 
1723   std::string RefCaptureDefaultCode = R"(
1724     struct A {
1725       void frob() {
1726         [&]() {
1727           int Foo = Bar;
1728           // [[p2]]
1729         }();
1730       }
1731 
1732       int Bar;
1733     };
1734   )";
1735   runDataflow(
1736       RefCaptureDefaultCode,
1737       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1738          ASTContext &ASTCtx) {
1739         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
1740         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
1741 
1742         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1743         ASSERT_THAT(ThisLoc, NotNull());
1744 
1745         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1746         ASSERT_THAT(BarDecl, NotNull());
1747 
1748         const auto *BarLoc =
1749             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1750         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1751 
1752         const Value *BarVal = Env.getValue(*BarLoc);
1753         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1754 
1755         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1756         ASSERT_THAT(FooDecl, NotNull());
1757         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1758       },
1759       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1760 
1761   std::string FreeFunctionLambdaCode = R"(
1762     void foo() {
1763       int Bar;
1764       [&]() {
1765         int Foo = Bar;
1766         // [[p3]]
1767       }();
1768     }
1769   )";
1770   runDataflow(
1771       FreeFunctionLambdaCode,
1772       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1773          ASTContext &ASTCtx) {
1774         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
1775         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
1776 
1777         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
1778       },
1779       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1780 }
1781 
1782 TEST(TransferTest, ConstructorInitializer) {
1783   std::string Code = R"(
1784     struct target {
1785       int Bar;
1786 
1787       target(int Foo) : Bar(Foo) {
1788         int Qux = Bar;
1789         // [[p]]
1790       }
1791     };
1792   )";
1793   runDataflow(
1794       Code,
1795       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1796          ASTContext &ASTCtx) {
1797         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1798         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1799 
1800         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1801         ASSERT_THAT(ThisLoc, NotNull());
1802 
1803         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1804         ASSERT_THAT(FooDecl, NotNull());
1805 
1806         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
1807 
1808         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1809         ASSERT_THAT(QuxDecl, NotNull());
1810         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
1811       });
1812 }
1813 
1814 TEST(TransferTest, DefaultInitializer) {
1815   std::string Code = R"(
1816     struct target {
1817       int Bar;
1818       int Baz = Bar;
1819 
1820       target(int Foo) : Bar(Foo) {
1821         int Qux = Baz;
1822         // [[p]]
1823       }
1824     };
1825   )";
1826   runDataflow(
1827       Code,
1828       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1829          ASTContext &ASTCtx) {
1830         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1831         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1832 
1833         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1834         ASSERT_THAT(ThisLoc, NotNull());
1835 
1836         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1837         ASSERT_THAT(FooDecl, NotNull());
1838 
1839         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
1840 
1841         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1842         ASSERT_THAT(QuxDecl, NotNull());
1843         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
1844       });
1845 }
1846 
1847 TEST(TransferTest, DefaultInitializerReference) {
1848   std::string Code = R"(
1849     struct target {
1850       int &Bar;
1851       int &Baz = Bar;
1852 
1853       target(int &Foo) : Bar(Foo) {
1854         int &Qux = Baz;
1855         // [[p]]
1856       }
1857     };
1858   )";
1859   runDataflow(
1860       Code,
1861       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1862          ASTContext &ASTCtx) {
1863         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1864         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1865 
1866         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1867         ASSERT_THAT(ThisLoc, NotNull());
1868 
1869         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1870         ASSERT_THAT(FooDecl, NotNull());
1871 
1872         const auto *FooLoc = Env.getStorageLocation(*FooDecl);
1873 
1874         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1875         ASSERT_THAT(QuxDecl, NotNull());
1876 
1877         const auto *QuxLoc = Env.getStorageLocation(*QuxDecl);
1878         EXPECT_EQ(QuxLoc, FooLoc);
1879       });
1880 }
1881 
1882 TEST(TransferTest, TemporaryObject) {
1883   std::string Code = R"(
1884     struct A {
1885       int Bar;
1886     };
1887 
1888     void target() {
1889       A Foo = A();
1890       (void)Foo.Bar;
1891       // [[p]]
1892     }
1893   )";
1894   runDataflow(
1895       Code,
1896       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1897          ASTContext &ASTCtx) {
1898         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1899         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1900 
1901         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1902         ASSERT_THAT(FooDecl, NotNull());
1903 
1904         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1905         ASSERT_THAT(BarDecl, NotNull());
1906 
1907         const auto *FooLoc =
1908             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1909         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
1910       });
1911 }
1912 
1913 TEST(TransferTest, ElidableConstructor) {
1914   // This test is effectively the same as TransferTest.TemporaryObject, but
1915   // the code is compiled as C++ 14.
1916   std::string Code = R"(
1917     struct A {
1918       int Bar;
1919     };
1920 
1921     void target() {
1922       A Foo = A();
1923       (void)Foo.Bar;
1924       // [[p]]
1925     }
1926   )";
1927   runDataflow(
1928       Code,
1929       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1930          ASTContext &ASTCtx) {
1931         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1932         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1933 
1934         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1935         ASSERT_THAT(FooDecl, NotNull());
1936 
1937         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1938         ASSERT_THAT(BarDecl, NotNull());
1939 
1940         const auto *FooLoc =
1941             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1942         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
1943       },
1944       LangStandard::lang_cxx14);
1945 }
1946 
1947 TEST(TransferTest, AssignmentOperator) {
1948   std::string Code = R"(
1949     struct A {
1950       int Baz;
1951     };
1952 
1953     void target() {
1954       A Foo = { 1 };
1955       A Bar = { 2 };
1956       // [[p1]]
1957       Foo = Bar;
1958       // [[p2]]
1959       Foo.Baz = 3;
1960       // [[p3]]
1961     }
1962   )";
1963   runDataflow(
1964       Code,
1965       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1966          ASTContext &ASTCtx) {
1967         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1968         ASSERT_THAT(FooDecl, NotNull());
1969 
1970         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1971         ASSERT_THAT(BarDecl, NotNull());
1972 
1973         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1974         ASSERT_THAT(BazDecl, NotNull());
1975 
1976         // Before copy assignment.
1977         {
1978           const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
1979 
1980           const auto *FooLoc1 =
1981               cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
1982           const auto *BarLoc1 =
1983               cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
1984           EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
1985 
1986           const auto *FooBazVal1 =
1987               cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
1988           const auto *BarBazVal1 =
1989               cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
1990           EXPECT_NE(FooBazVal1, BarBazVal1);
1991         }
1992 
1993         // After copy assignment.
1994         {
1995           const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
1996 
1997           const auto *FooLoc2 =
1998               cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
1999           const auto *BarLoc2 =
2000               cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl));
2001 
2002           const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
2003           const auto *BarVal2 = cast<RecordValue>(Env2.getValue(*BarLoc2));
2004           EXPECT_NE(FooVal2, BarVal2);
2005 
2006           EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2));
2007 
2008           const auto *FooBazVal2 =
2009               cast<IntegerValue>(getFieldValue(FooLoc2, *BazDecl, Env2));
2010           const auto *BarBazVal2 =
2011               cast<IntegerValue>(getFieldValue(BarLoc2, *BazDecl, Env2));
2012           EXPECT_EQ(FooBazVal2, BarBazVal2);
2013         }
2014 
2015         // After value update.
2016         {
2017           const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
2018 
2019           const auto *FooLoc3 =
2020               cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl));
2021           const auto *BarLoc3 =
2022               cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl));
2023           EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3));
2024 
2025           const auto *FooBazVal3 =
2026               cast<IntegerValue>(getFieldValue(FooLoc3, *BazDecl, Env3));
2027           const auto *BarBazVal3 =
2028               cast<IntegerValue>(getFieldValue(BarLoc3, *BazDecl, Env3));
2029           EXPECT_NE(FooBazVal3, BarBazVal3);
2030         }
2031       });
2032 }
2033 
2034 TEST(TransferTest, AssignmentOperatorFromCallResult) {
2035   std::string Code = R"(
2036     struct A {};
2037     A ReturnA();
2038 
2039     void target() {
2040       A MyA;
2041       MyA = ReturnA();
2042     }
2043   )";
2044   runDataflow(
2045       Code,
2046       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2047          ASTContext &ASTCtx) {
2048         // As of this writing, we don't produce a `Value` for the call
2049         // `ReturnA()`. The only condition we're testing for is that the
2050         // analysis should not crash in this case.
2051       });
2052 }
2053 
2054 TEST(TransferTest, CopyConstructor) {
2055   std::string Code = R"(
2056     struct A {
2057       int Baz;
2058     };
2059 
2060     void target() {
2061       A Foo = { 1 };
2062       A Bar = Foo;
2063       // [[after_copy]]
2064       Foo.Baz = 2;
2065       // [[after_update]]
2066     }
2067   )";
2068   runDataflow(
2069       Code,
2070       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2071          ASTContext &ASTCtx) {
2072         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2073         ASSERT_THAT(FooDecl, NotNull());
2074 
2075         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2076         ASSERT_THAT(BarDecl, NotNull());
2077 
2078         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2079         ASSERT_THAT(BazDecl, NotNull());
2080 
2081         // after_copy
2082         {
2083           const Environment &Env =
2084               getEnvironmentAtAnnotation(Results, "after_copy");
2085 
2086           const auto *FooLoc =
2087               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2088           const auto *BarLoc =
2089               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2090 
2091           // `Foo` and `Bar` have different `RecordValue`s associated with them.
2092           const auto *FooVal = cast<RecordValue>(Env.getValue(*FooLoc));
2093           const auto *BarVal = cast<RecordValue>(Env.getValue(*BarLoc));
2094           EXPECT_NE(FooVal, BarVal);
2095 
2096           // But the records compare equal.
2097           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2098 
2099           // In particular, the value of `Baz` in both records is the same.
2100           const auto *FooBazVal =
2101               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2102           const auto *BarBazVal =
2103               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2104           EXPECT_EQ(FooBazVal, BarBazVal);
2105         }
2106 
2107         // after_update
2108         {
2109           const Environment &Env =
2110               getEnvironmentAtAnnotation(Results, "after_update");
2111 
2112           const auto *FooLoc =
2113               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2114           const auto *BarLoc =
2115               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2116 
2117           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2118 
2119           const auto *FooBazVal =
2120               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2121           const auto *BarBazVal =
2122               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2123           EXPECT_NE(FooBazVal, BarBazVal);
2124         }
2125       });
2126 }
2127 
2128 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2129   std::string Code = R"(
2130     struct A {
2131       int Baz;
2132       A() = default;
2133       A(const A& a, bool def = true) { Baz = a.Baz; }
2134     };
2135 
2136     void target() {
2137       A Foo;
2138       (void)Foo.Baz;
2139       A Bar = Foo;
2140       // [[p]]
2141     }
2142   )";
2143   runDataflow(
2144       Code,
2145       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2146          ASTContext &ASTCtx) {
2147         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2148         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2149 
2150         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2151         ASSERT_THAT(FooDecl, NotNull());
2152 
2153         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2154         ASSERT_THAT(BarDecl, NotNull());
2155 
2156         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2157         ASSERT_THAT(BazDecl, NotNull());
2158 
2159         const auto *FooLoc =
2160             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2161         const auto *BarLoc =
2162             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2163         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2164 
2165         const auto *FooBazVal =
2166             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2167         const auto *BarBazVal =
2168             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2169         EXPECT_EQ(FooBazVal, BarBazVal);
2170       });
2171 }
2172 
2173 TEST(TransferTest, CopyConstructorWithParens) {
2174   std::string Code = R"(
2175     struct A {
2176       int Baz;
2177     };
2178 
2179     void target() {
2180       A Foo;
2181       (void)Foo.Baz;
2182       A Bar((A(Foo)));
2183       // [[p]]
2184     }
2185   )";
2186   runDataflow(
2187       Code,
2188       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2189          ASTContext &ASTCtx) {
2190         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2191         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2192 
2193         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2194         ASSERT_THAT(FooDecl, NotNull());
2195 
2196         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2197         ASSERT_THAT(BarDecl, NotNull());
2198 
2199         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2200         ASSERT_THAT(BazDecl, NotNull());
2201 
2202         const auto *FooLoc =
2203             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2204         const auto *BarLoc =
2205             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2206         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2207 
2208         const auto *FooBazVal =
2209             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2210         const auto *BarBazVal =
2211             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2212         EXPECT_EQ(FooBazVal, BarBazVal);
2213       });
2214 }
2215 
2216 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {
2217   std::string Code = R"(
2218   struct A {
2219     int Baz;
2220   };
2221   void target() {
2222     A Foo = {3};
2223     (void)Foo.Baz;
2224     A Bar = {A(Foo)};
2225     // [[p]]
2226   }
2227   )";
2228   runDataflow(
2229       Code,
2230       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2231          ASTContext &ASTCtx) {
2232         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2233 
2234         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2235 
2236         const auto &FooLoc =
2237             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2238         const auto &BarLoc =
2239             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2240 
2241         const auto *FooBazVal =
2242             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2243         const auto *BarBazVal =
2244             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2245         EXPECT_EQ(FooBazVal, BarBazVal);
2246       });
2247 }
2248 
2249 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2250   // This is a crash repro.
2251   std::string Code = R"(
2252     struct S {};
2253     const S &returnsSRef();
2254     void target() {
2255       S s(returnsSRef());
2256     }
2257   )";
2258   runDataflow(
2259       Code,
2260       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2261          ASTContext &ASTCtx) {});
2262 }
2263 
2264 TEST(TransferTest, MoveConstructor) {
2265   std::string Code = R"(
2266     namespace std {
2267 
2268     template <typename T> struct remove_reference      { using type = T; };
2269     template <typename T> struct remove_reference<T&>  { using type = T; };
2270     template <typename T> struct remove_reference<T&&> { using type = T; };
2271 
2272     template <typename T>
2273     using remove_reference_t = typename remove_reference<T>::type;
2274 
2275     template <typename T>
2276     std::remove_reference_t<T>&& move(T&& x);
2277 
2278     } // namespace std
2279 
2280     struct A {
2281       int Baz;
2282     };
2283 
2284     void target() {
2285       A Foo;
2286       A Bar;
2287       (void)Foo.Baz;
2288       // [[p1]]
2289       Foo = std::move(Bar);
2290       // [[p2]]
2291     }
2292   )";
2293   runDataflow(
2294       Code,
2295       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2296          ASTContext &ASTCtx) {
2297         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2298         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2299         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2300 
2301         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2302         ASSERT_THAT(FooDecl, NotNull());
2303 
2304         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2305         ASSERT_THAT(BarDecl, NotNull());
2306 
2307         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2308         ASSERT_THAT(BazDecl, NotNull());
2309 
2310         const auto *FooLoc1 =
2311             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2312         const auto *BarLoc1 =
2313             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2314 
2315         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2316 
2317         const auto *FooVal1 = cast<RecordValue>(Env1.getValue(*FooLoc1));
2318         const auto *BarVal1 = cast<RecordValue>(Env1.getValue(*BarLoc1));
2319         EXPECT_NE(FooVal1, BarVal1);
2320 
2321         const auto *FooBazVal1 =
2322             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2323         const auto *BarBazVal1 =
2324             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2325         EXPECT_NE(FooBazVal1, BarBazVal1);
2326 
2327         const auto *FooLoc2 =
2328             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2329         const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
2330         EXPECT_NE(FooVal2, BarVal1);
2331         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2332 
2333         const auto *FooBazVal2 =
2334             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2335         EXPECT_EQ(FooBazVal2, BarBazVal1);
2336       });
2337 }
2338 
2339 TEST(TransferTest, BindTemporary) {
2340   std::string Code = R"(
2341     struct A {
2342       virtual ~A() = default;
2343 
2344       int Baz;
2345     };
2346 
2347     void target(A Foo) {
2348       int Bar = A(Foo).Baz;
2349       // [[p]]
2350     }
2351   )";
2352   runDataflow(
2353       Code,
2354       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2355          ASTContext &ASTCtx) {
2356         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2357         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2358 
2359         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2360         ASSERT_THAT(FooDecl, NotNull());
2361 
2362         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2363         ASSERT_THAT(BarDecl, NotNull());
2364 
2365         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2366         ASSERT_THAT(BazDecl, NotNull());
2367 
2368         const auto &FooVal = *cast<RecordValue>(Env.getValue(*FooDecl));
2369         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2370         EXPECT_EQ(BarVal, getFieldValue(&FooVal, *BazDecl, Env));
2371       });
2372 }
2373 
2374 TEST(TransferTest, StaticCast) {
2375   std::string Code = R"(
2376     void target(int Foo) {
2377       int Bar = static_cast<int>(Foo);
2378       // [[p]]
2379     }
2380   )";
2381   runDataflow(
2382       Code,
2383       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2384          ASTContext &ASTCtx) {
2385         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2386         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2387 
2388         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2389         ASSERT_THAT(FooDecl, NotNull());
2390 
2391         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2392         ASSERT_THAT(BarDecl, NotNull());
2393 
2394         const auto *FooVal = Env.getValue(*FooDecl);
2395         const auto *BarVal = Env.getValue(*BarDecl);
2396         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2397         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2398         EXPECT_EQ(FooVal, BarVal);
2399       });
2400 }
2401 
2402 TEST(TransferTest, IntegralCast) {
2403   std::string Code = R"(
2404     void target(int Foo) {
2405       long Bar = Foo;
2406       // [[p]]
2407     }
2408   )";
2409   runDataflow(
2410       Code,
2411       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2412          ASTContext &ASTCtx) {
2413         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2414         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2415 
2416         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2417         ASSERT_THAT(FooDecl, NotNull());
2418 
2419         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2420         ASSERT_THAT(BarDecl, NotNull());
2421 
2422         const auto *FooVal = Env.getValue(*FooDecl);
2423         const auto *BarVal = Env.getValue(*BarDecl);
2424         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2425         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2426         EXPECT_EQ(FooVal, BarVal);
2427       });
2428 }
2429 
2430 TEST(TransferTest, IntegraltoBooleanCast) {
2431   std::string Code = R"(
2432     void target(int Foo) {
2433       bool Bar = Foo;
2434       // [[p]]
2435     }
2436   )";
2437   runDataflow(
2438       Code,
2439       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2440          ASTContext &ASTCtx) {
2441         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2442         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2443 
2444         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2445         ASSERT_THAT(FooDecl, NotNull());
2446 
2447         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2448         ASSERT_THAT(BarDecl, NotNull());
2449 
2450         const auto *FooVal = Env.getValue(*FooDecl);
2451         const auto *BarVal = Env.getValue(*BarDecl);
2452         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2453         EXPECT_TRUE(isa<BoolValue>(BarVal));
2454       });
2455 }
2456 
2457 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2458   std::string Code = R"(
2459     void target(bool Foo) {
2460       int Zab = Foo;
2461       bool Bar = Zab;
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 auto *FooVal = Env.getValue(*FooDecl);
2479         const auto *BarVal = Env.getValue(*BarDecl);
2480         EXPECT_TRUE(isa<BoolValue>(FooVal));
2481         EXPECT_TRUE(isa<BoolValue>(BarVal));
2482         EXPECT_EQ(FooVal, BarVal);
2483       });
2484 }
2485 
2486 TEST(TransferTest, NullToPointerCast) {
2487   std::string Code = R"(
2488     using my_nullptr_t = decltype(nullptr);
2489     struct Baz {};
2490     void target() {
2491       int *FooX = nullptr;
2492       int *FooY = nullptr;
2493       bool **Bar = nullptr;
2494       Baz *Baz = nullptr;
2495       my_nullptr_t Null = 0;
2496       // [[p]]
2497     }
2498   )";
2499   runDataflow(
2500       Code,
2501       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2502          ASTContext &ASTCtx) {
2503         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2504         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2505 
2506         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2507         ASSERT_THAT(FooXDecl, NotNull());
2508 
2509         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2510         ASSERT_THAT(FooYDecl, NotNull());
2511 
2512         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2513         ASSERT_THAT(BarDecl, NotNull());
2514 
2515         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2516         ASSERT_THAT(BazDecl, NotNull());
2517 
2518         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2519         ASSERT_THAT(NullDecl, NotNull());
2520 
2521         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
2522         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
2523         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2524         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
2525         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
2526 
2527         EXPECT_EQ(FooXVal, FooYVal);
2528         EXPECT_NE(FooXVal, BarVal);
2529         EXPECT_NE(FooXVal, BazVal);
2530         EXPECT_NE(BarVal, BazVal);
2531 
2532         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2533         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2534         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2535 
2536         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2537         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2538         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2539 
2540         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2541         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
2542         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2543 
2544         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
2545         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2546         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2547       });
2548 }
2549 
2550 TEST(TransferTest, PointerToMemberVariable) {
2551   std::string Code = R"(
2552     struct S {
2553       int i;
2554     };
2555     void target() {
2556       int S::*MemberPointer = &S::i;
2557       // [[p]]
2558     }
2559   )";
2560   runDataflow(
2561       Code,
2562       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2563          ASTContext &ASTCtx) {
2564         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2565 
2566         const ValueDecl *MemberPointerDecl =
2567             findValueDecl(ASTCtx, "MemberPointer");
2568         ASSERT_THAT(MemberPointerDecl, NotNull());
2569         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2570       });
2571 }
2572 
2573 TEST(TransferTest, PointerToMemberFunction) {
2574   std::string Code = R"(
2575     struct S {
2576       void Method();
2577     };
2578     void target() {
2579       void (S::*MemberPointer)() = &S::Method;
2580       // [[p]]
2581     }
2582   )";
2583   runDataflow(
2584       Code,
2585       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2586          ASTContext &ASTCtx) {
2587         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2588 
2589         const ValueDecl *MemberPointerDecl =
2590             findValueDecl(ASTCtx, "MemberPointer");
2591         ASSERT_THAT(MemberPointerDecl, NotNull());
2592         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2593       });
2594 }
2595 
2596 TEST(TransferTest, NullToMemberPointerCast) {
2597   std::string Code = R"(
2598     struct Foo {};
2599     void target() {
2600       int Foo::*MemberPointer = nullptr;
2601       // [[p]]
2602     }
2603   )";
2604   runDataflow(
2605       Code,
2606       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2607          ASTContext &ASTCtx) {
2608         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2609         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2610 
2611         const ValueDecl *MemberPointerDecl =
2612             findValueDecl(ASTCtx, "MemberPointer");
2613         ASSERT_THAT(MemberPointerDecl, NotNull());
2614         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2615       });
2616 }
2617 
2618 TEST(TransferTest, AddrOfValue) {
2619   std::string Code = R"(
2620     void target() {
2621       int Foo;
2622       int *Bar = &Foo;
2623       // [[p]]
2624     }
2625   )";
2626   runDataflow(
2627       Code,
2628       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2629          ASTContext &ASTCtx) {
2630         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2631         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2632 
2633         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2634         ASSERT_THAT(FooDecl, NotNull());
2635 
2636         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2637         ASSERT_THAT(BarDecl, NotNull());
2638 
2639         const auto *FooLoc =
2640             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
2641         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2642         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2643       });
2644 }
2645 
2646 TEST(TransferTest, AddrOfReference) {
2647   std::string Code = R"(
2648     void target(int *Foo) {
2649       int *Bar = &(*Foo);
2650       // [[p]]
2651     }
2652   )";
2653   runDataflow(
2654       Code,
2655       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2656          ASTContext &ASTCtx) {
2657         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2658         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2659 
2660         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2661         ASSERT_THAT(FooDecl, NotNull());
2662 
2663         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2664         ASSERT_THAT(BarDecl, NotNull());
2665 
2666         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
2667         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2668         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2669       });
2670 }
2671 
2672 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
2673   std::string Code = R"(
2674     template <typename T>
2675     void target() {}
2676   )";
2677   ASSERT_THAT_ERROR(
2678       checkDataflowWithNoopAnalysis(Code),
2679       llvm::FailedWithMessage("Cannot analyze templated declarations"));
2680 }
2681 
2682 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
2683   std::string Code = R"(
2684     template <typename T>
2685     struct A {
2686       void target() {}
2687     };
2688   )";
2689   ASSERT_THAT_ERROR(
2690       checkDataflowWithNoopAnalysis(Code),
2691       llvm::FailedWithMessage("Cannot analyze templated declarations"));
2692 }
2693 
2694 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
2695   std::string Code = R"(
2696     struct A {};
2697 
2698     void target(A Foo, A Bar, bool Cond) {
2699       A Baz = Cond ?  Foo : Bar;
2700       /*[[p]]*/
2701     }
2702   )";
2703   runDataflow(
2704       Code,
2705       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2706          ASTContext &ASTCtx) {
2707         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2708         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2709 
2710         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2711         ASSERT_THAT(FooDecl, NotNull());
2712 
2713         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2714         ASSERT_THAT(BarDecl, NotNull());
2715 
2716         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2717         ASSERT_THAT(BazDecl, NotNull());
2718 
2719         const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
2720         const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
2721 
2722         const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
2723         ASSERT_THAT(BazVal, NotNull());
2724 
2725         EXPECT_NE(BazVal, FooVal);
2726         EXPECT_NE(BazVal, BarVal);
2727       });
2728 }
2729 
2730 TEST(TransferTest, VarDeclInDoWhile) {
2731   std::string Code = R"(
2732     void target(int *Foo) {
2733       do {
2734         int Bar = *Foo;
2735         // [[in_loop]]
2736       } while (false);
2737       (void)0;
2738       // [[after_loop]]
2739     }
2740   )";
2741   runDataflow(
2742       Code,
2743       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2744          ASTContext &ASTCtx) {
2745         const Environment &EnvInLoop =
2746             getEnvironmentAtAnnotation(Results, "in_loop");
2747         const Environment &EnvAfterLoop =
2748             getEnvironmentAtAnnotation(Results, "after_loop");
2749 
2750         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2751         ASSERT_THAT(FooDecl, NotNull());
2752 
2753         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2754         ASSERT_THAT(BarDecl, NotNull());
2755 
2756         const auto *FooVal =
2757             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
2758         const auto *FooPointeeVal =
2759             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
2760 
2761         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
2762         EXPECT_EQ(BarVal, FooPointeeVal);
2763 
2764         // FIXME: This assertion documents current behavior, but we would prefer
2765         // declarations to be removed from the environment when their lifetime
2766         // ends. Once this is the case, change this assertion accordingly.
2767         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), BarVal);
2768       });
2769 }
2770 
2771 TEST(TransferTest, UnreachableAfterWhileTrue) {
2772   std::string Code = R"(
2773     void target() {
2774       while (true) {}
2775       (void)0;
2776       /*[[p]]*/
2777     }
2778   )";
2779   runDataflow(
2780       Code,
2781       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2782          ASTContext &ASTCtx) {
2783         // The node after the while-true is pruned because it is trivially
2784         // known to be unreachable.
2785         ASSERT_TRUE(Results.empty());
2786       });
2787 }
2788 
2789 TEST(TransferTest, AggregateInitialization) {
2790   std::string BracesCode = R"(
2791     struct A {
2792       int Foo;
2793     };
2794 
2795     struct B {
2796       int Bar;
2797       A Baz;
2798       int Qux;
2799     };
2800 
2801     void target(int BarArg, int FooArg, int QuxArg) {
2802       B Quux{BarArg, {FooArg}, QuxArg};
2803       B OtherB;
2804       /*[[p]]*/
2805     }
2806   )";
2807   std::string BraceElisionCode = R"(
2808     struct A {
2809       int Foo;
2810     };
2811 
2812     struct B {
2813       int Bar;
2814       A Baz;
2815       int Qux;
2816     };
2817 
2818     void target(int BarArg, int FooArg, int QuxArg) {
2819       B Quux = {BarArg, FooArg, QuxArg};
2820       B OtherB;
2821       /*[[p]]*/
2822     }
2823   )";
2824   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
2825     runDataflow(
2826         Code,
2827         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2828            ASTContext &ASTCtx) {
2829           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2830           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2831 
2832           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2833           ASSERT_THAT(FooDecl, NotNull());
2834 
2835           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2836           ASSERT_THAT(BarDecl, NotNull());
2837 
2838           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2839           ASSERT_THAT(BazDecl, NotNull());
2840 
2841           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2842           ASSERT_THAT(QuxDecl, NotNull());
2843 
2844           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2845           ASSERT_THAT(FooArgDecl, NotNull());
2846 
2847           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2848           ASSERT_THAT(BarArgDecl, NotNull());
2849 
2850           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2851           ASSERT_THAT(QuxArgDecl, NotNull());
2852 
2853           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2854           ASSERT_THAT(QuuxDecl, NotNull());
2855 
2856           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
2857           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
2858           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
2859 
2860           const auto *QuuxVal = cast<RecordValue>(Env.getValue(*QuuxDecl));
2861           ASSERT_THAT(QuuxVal, NotNull());
2862 
2863           const auto *BazVal =
2864               cast<RecordValue>(getFieldValue(QuuxVal, *BazDecl, Env));
2865           ASSERT_THAT(BazVal, NotNull());
2866 
2867           EXPECT_EQ(getFieldValue(QuuxVal, *BarDecl, Env), BarArgVal);
2868           EXPECT_EQ(getFieldValue(BazVal, *FooDecl, Env), FooArgVal);
2869           EXPECT_EQ(getFieldValue(QuuxVal, *QuxDecl, Env), QuxArgVal);
2870 
2871           // Check that fields initialized in an initializer list are always
2872           // modeled in other instances of the same type.
2873           const auto &OtherBLoc =
2874               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
2875           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
2876           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
2877           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
2878         });
2879   }
2880 }
2881 
2882 TEST(TransferTest, AggregateInitializationReferenceField) {
2883   std::string Code = R"(
2884     struct S {
2885       int &RefField;
2886     };
2887 
2888     void target(int i) {
2889       S s = { i };
2890       /*[[p]]*/
2891     }
2892   )";
2893   runDataflow(
2894       Code,
2895       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2896          ASTContext &ASTCtx) {
2897         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2898 
2899         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
2900 
2901         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
2902         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
2903 
2904         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
2905       });
2906 }
2907 
2908 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
2909   std::string Code = R"(
2910     struct S {
2911       int i1;
2912       int i2;
2913     };
2914 
2915     void target(int i) {
2916       S s = { i };
2917       /*[[p]]*/
2918     }
2919   )";
2920   runDataflow(
2921       Code,
2922       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2923          ASTContext &ASTCtx) {
2924         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2925 
2926         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
2927         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
2928 
2929         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
2930 
2931         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
2932         auto &I1Value =
2933             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
2934         EXPECT_EQ(&I1Value, &IValue);
2935         auto &I2Value =
2936             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
2937         EXPECT_NE(&I2Value, &IValue);
2938       });
2939 }
2940 
2941 TEST(TransferTest, AssignToUnionMember) {
2942   std::string Code = R"(
2943     union A {
2944       int Foo;
2945     };
2946 
2947     void target(int Bar) {
2948       A Baz;
2949       Baz.Foo = Bar;
2950       // [[p]]
2951     }
2952   )";
2953   runDataflow(
2954       Code,
2955       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2956          ASTContext &ASTCtx) {
2957         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2958         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2959 
2960         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2961         ASSERT_THAT(BazDecl, NotNull());
2962         ASSERT_TRUE(BazDecl->getType()->isUnionType());
2963 
2964         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
2965         FieldDecl *FooDecl = nullptr;
2966         for (FieldDecl *Field : BazFields) {
2967           if (Field->getNameAsString() == "Foo") {
2968             FooDecl = Field;
2969           } else {
2970             FAIL() << "Unexpected field: " << Field->getNameAsString();
2971           }
2972         }
2973         ASSERT_THAT(FooDecl, NotNull());
2974 
2975         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
2976             Env.getStorageLocation(*BazDecl));
2977         ASSERT_THAT(BazLoc, NotNull());
2978         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
2979 
2980         const auto *FooVal =
2981             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
2982 
2983         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2984         ASSERT_THAT(BarDecl, NotNull());
2985         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
2986         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2987 
2988         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
2989       });
2990 }
2991 
2992 TEST(TransferTest, AssignFromBoolLiteral) {
2993   std::string Code = R"(
2994     void target() {
2995       bool Foo = true;
2996       bool Bar = false;
2997       // [[p]]
2998     }
2999   )";
3000   runDataflow(
3001       Code,
3002       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3003          ASTContext &ASTCtx) {
3004         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3005         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3006 
3007         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3008         ASSERT_THAT(FooDecl, NotNull());
3009 
3010         const auto *FooVal =
3011             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3012         ASSERT_THAT(FooVal, NotNull());
3013 
3014         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3015         ASSERT_THAT(BarDecl, NotNull());
3016 
3017         const auto *BarVal =
3018             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl));
3019         ASSERT_THAT(BarVal, NotNull());
3020 
3021         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3022         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3023       });
3024 }
3025 
3026 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3027   {
3028     std::string Code = R"(
3029     void target(bool Foo, bool Bar, bool Qux) {
3030       bool Baz = (Foo) && (Bar || Qux);
3031       // [[p]]
3032     }
3033   )";
3034     runDataflow(
3035         Code,
3036         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3037            ASTContext &ASTCtx) {
3038           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3039           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3040 
3041           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3042           ASSERT_THAT(FooDecl, NotNull());
3043 
3044           const auto *FooVal =
3045               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3046           ASSERT_THAT(FooVal, NotNull());
3047 
3048           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3049           ASSERT_THAT(BarDecl, NotNull());
3050 
3051           const auto *BarVal =
3052               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3053           ASSERT_THAT(BarVal, NotNull());
3054 
3055           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3056           ASSERT_THAT(QuxDecl, NotNull());
3057 
3058           const auto *QuxVal =
3059               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3060           ASSERT_THAT(QuxVal, NotNull());
3061 
3062           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3063           ASSERT_THAT(BazDecl, NotNull());
3064 
3065           const auto *BazVal =
3066               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3067           ASSERT_THAT(BazVal, NotNull());
3068           auto &A = Env.arena();
3069           EXPECT_EQ(&BazVal->formula(),
3070                     &A.makeAnd(FooVal->formula(),
3071                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3072         });
3073   }
3074 
3075   {
3076     std::string Code = R"(
3077     void target(bool Foo, bool Bar, bool Qux) {
3078       bool Baz = (Foo && Qux) || (Bar);
3079       // [[p]]
3080     }
3081   )";
3082     runDataflow(
3083         Code,
3084         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3085            ASTContext &ASTCtx) {
3086           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3087           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3088 
3089           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3090           ASSERT_THAT(FooDecl, NotNull());
3091 
3092           const auto *FooVal =
3093               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3094           ASSERT_THAT(FooVal, NotNull());
3095 
3096           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3097           ASSERT_THAT(BarDecl, NotNull());
3098 
3099           const auto *BarVal =
3100               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3101           ASSERT_THAT(BarVal, NotNull());
3102 
3103           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3104           ASSERT_THAT(QuxDecl, NotNull());
3105 
3106           const auto *QuxVal =
3107               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3108           ASSERT_THAT(QuxVal, NotNull());
3109 
3110           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3111           ASSERT_THAT(BazDecl, NotNull());
3112 
3113           const auto *BazVal =
3114               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3115           ASSERT_THAT(BazVal, NotNull());
3116           auto &A = Env.arena();
3117           EXPECT_EQ(&BazVal->formula(),
3118                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3119                               BarVal->formula()));
3120         });
3121   }
3122 
3123   {
3124     std::string Code = R"(
3125       void target(bool A, bool B, bool C, bool D) {
3126         bool Foo = ((A && B) && C) && D;
3127         // [[p]]
3128       }
3129     )";
3130     runDataflow(
3131         Code,
3132         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3133            ASTContext &ASTCtx) {
3134           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3135           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3136 
3137           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
3138           ASSERT_THAT(ADecl, NotNull());
3139 
3140           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
3141           ASSERT_THAT(AVal, NotNull());
3142 
3143           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3144           ASSERT_THAT(BDecl, NotNull());
3145 
3146           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
3147           ASSERT_THAT(BVal, NotNull());
3148 
3149           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3150           ASSERT_THAT(CDecl, NotNull());
3151 
3152           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3153           ASSERT_THAT(CVal, NotNull());
3154 
3155           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3156           ASSERT_THAT(DDecl, NotNull());
3157 
3158           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3159           ASSERT_THAT(DVal, NotNull());
3160 
3161           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3162           ASSERT_THAT(FooDecl, NotNull());
3163 
3164           const auto *FooVal =
3165               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3166           ASSERT_THAT(FooVal, NotNull());
3167           auto &A = Env.arena();
3168           EXPECT_EQ(
3169               &FooVal->formula(),
3170               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
3171                                    CVal->formula()),
3172                          DVal->formula()));
3173         });
3174   }
3175 }
3176 
3177 TEST(TransferTest, AssignFromBoolNegation) {
3178   std::string Code = R"(
3179     void target() {
3180       bool Foo = true;
3181       bool Bar = !(Foo);
3182       // [[p]]
3183     }
3184   )";
3185   runDataflow(
3186       Code,
3187       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3188          ASTContext &ASTCtx) {
3189         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3190         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3191 
3192         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3193         ASSERT_THAT(FooDecl, NotNull());
3194 
3195         const auto *FooVal =
3196             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3197         ASSERT_THAT(FooVal, NotNull());
3198 
3199         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3200         ASSERT_THAT(BarDecl, NotNull());
3201 
3202         const auto *BarVal =
3203             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3204         ASSERT_THAT(BarVal, NotNull());
3205         auto &A = Env.arena();
3206         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
3207       });
3208 }
3209 
3210 TEST(TransferTest, BuiltinExpect) {
3211   std::string Code = R"(
3212     void target(long Foo) {
3213       long Bar = __builtin_expect(Foo, true);
3214       /*[[p]]*/
3215     }
3216   )";
3217   runDataflow(
3218       Code,
3219       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3220          ASTContext &ASTCtx) {
3221         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3222         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3223 
3224         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3225         ASSERT_THAT(FooDecl, NotNull());
3226 
3227         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3228         ASSERT_THAT(BarDecl, NotNull());
3229 
3230         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3231       });
3232 }
3233 
3234 // `__builtin_expect` takes and returns a `long` argument, so other types
3235 // involve casts. This verifies that we identify the input and output in that
3236 // case.
3237 TEST(TransferTest, BuiltinExpectBoolArg) {
3238   std::string Code = R"(
3239     void target(bool Foo) {
3240       bool Bar = __builtin_expect(Foo, true);
3241       /*[[p]]*/
3242     }
3243   )";
3244   runDataflow(
3245       Code,
3246       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3247          ASTContext &ASTCtx) {
3248         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3249         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3250 
3251         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3252         ASSERT_THAT(FooDecl, NotNull());
3253 
3254         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3255         ASSERT_THAT(BarDecl, NotNull());
3256 
3257         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3258       });
3259 }
3260 
3261 TEST(TransferTest, BuiltinUnreachable) {
3262   std::string Code = R"(
3263     void target(bool Foo) {
3264       bool Bar = false;
3265       if (Foo)
3266         Bar = Foo;
3267       else
3268         __builtin_unreachable();
3269       (void)0;
3270       /*[[p]]*/
3271     }
3272   )";
3273   runDataflow(
3274       Code,
3275       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3276          ASTContext &ASTCtx) {
3277         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3278         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3279 
3280         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3281         ASSERT_THAT(FooDecl, NotNull());
3282 
3283         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3284         ASSERT_THAT(BarDecl, NotNull());
3285 
3286         // `__builtin_unreachable` promises that the code is
3287         // unreachable, so the compiler treats the "then" branch as the
3288         // only possible predecessor of this statement.
3289         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3290       });
3291 }
3292 
3293 TEST(TransferTest, BuiltinTrap) {
3294   std::string Code = R"(
3295     void target(bool Foo) {
3296       bool Bar = false;
3297       if (Foo)
3298         Bar = Foo;
3299       else
3300         __builtin_trap();
3301       (void)0;
3302       /*[[p]]*/
3303     }
3304   )";
3305   runDataflow(
3306       Code,
3307       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3308          ASTContext &ASTCtx) {
3309         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3310         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3311 
3312         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3313         ASSERT_THAT(FooDecl, NotNull());
3314 
3315         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3316         ASSERT_THAT(BarDecl, NotNull());
3317 
3318         // `__builtin_trap` ensures program termination, so only the
3319         // "then" branch is a predecessor of this statement.
3320         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3321       });
3322 }
3323 
3324 TEST(TransferTest, BuiltinDebugTrap) {
3325   std::string Code = R"(
3326     void target(bool Foo) {
3327       bool Bar = false;
3328       if (Foo)
3329         Bar = Foo;
3330       else
3331         __builtin_debugtrap();
3332       (void)0;
3333       /*[[p]]*/
3334     }
3335   )";
3336   runDataflow(
3337       Code,
3338       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3339          ASTContext &ASTCtx) {
3340         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3341         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3342 
3343         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3344         ASSERT_THAT(FooDecl, NotNull());
3345 
3346         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3347         ASSERT_THAT(BarDecl, NotNull());
3348 
3349         // `__builtin_debugtrap` doesn't ensure program termination.
3350         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3351       });
3352 }
3353 
3354 TEST(TransferTest, StaticIntSingleVarDecl) {
3355   std::string Code = R"(
3356     void target() {
3357       static int Foo;
3358       // [[p]]
3359     }
3360   )";
3361   runDataflow(
3362       Code,
3363       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3364          ASTContext &ASTCtx) {
3365         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3366         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3367 
3368         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3369         ASSERT_THAT(FooDecl, NotNull());
3370 
3371         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3372         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3373 
3374         const Value *FooVal = Env.getValue(*FooLoc);
3375         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3376       });
3377 }
3378 
3379 TEST(TransferTest, StaticIntGroupVarDecl) {
3380   std::string Code = R"(
3381     void target() {
3382       static int Foo, Bar;
3383       (void)0;
3384       // [[p]]
3385     }
3386   )";
3387   runDataflow(
3388       Code,
3389       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3390          ASTContext &ASTCtx) {
3391         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3392         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3393 
3394         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3395         ASSERT_THAT(FooDecl, NotNull());
3396 
3397         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3398         ASSERT_THAT(BarDecl, NotNull());
3399 
3400         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3401         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3402 
3403         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3404         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3405 
3406         const Value *FooVal = Env.getValue(*FooLoc);
3407         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3408 
3409         const Value *BarVal = Env.getValue(*BarLoc);
3410         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3411 
3412         EXPECT_NE(FooVal, BarVal);
3413       });
3414 }
3415 
3416 TEST(TransferTest, GlobalIntVarDecl) {
3417   std::string Code = R"(
3418     static int Foo;
3419 
3420     void target() {
3421       int Bar = Foo;
3422       int Baz = Foo;
3423       // [[p]]
3424     }
3425   )";
3426   runDataflow(
3427       Code,
3428       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3429          ASTContext &ASTCtx) {
3430         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3431         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3432 
3433         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3434         ASSERT_THAT(BarDecl, NotNull());
3435 
3436         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3437         ASSERT_THAT(BazDecl, NotNull());
3438 
3439         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3440         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3441         EXPECT_EQ(BarVal, BazVal);
3442       });
3443 }
3444 
3445 TEST(TransferTest, StaticMemberIntVarDecl) {
3446   std::string Code = R"(
3447     struct A {
3448       static int Foo;
3449     };
3450 
3451     void target(A a) {
3452       int Bar = a.Foo;
3453       int Baz = a.Foo;
3454       // [[p]]
3455     }
3456   )";
3457   runDataflow(
3458       Code,
3459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3460          ASTContext &ASTCtx) {
3461         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3462         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3463 
3464         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3465         ASSERT_THAT(BarDecl, NotNull());
3466 
3467         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3468         ASSERT_THAT(BazDecl, NotNull());
3469 
3470         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3471         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3472         EXPECT_EQ(BarVal, BazVal);
3473       });
3474 }
3475 
3476 TEST(TransferTest, StaticMemberRefVarDecl) {
3477   std::string Code = R"(
3478     struct A {
3479       static int &Foo;
3480     };
3481 
3482     void target(A a) {
3483       int Bar = a.Foo;
3484       int Baz = a.Foo;
3485       // [[p]]
3486     }
3487   )";
3488   runDataflow(
3489       Code,
3490       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3491          ASTContext &ASTCtx) {
3492         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3493         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3494 
3495         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3496         ASSERT_THAT(BarDecl, NotNull());
3497 
3498         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3499         ASSERT_THAT(BazDecl, NotNull());
3500 
3501         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3502         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3503         EXPECT_EQ(BarVal, BazVal);
3504       });
3505 }
3506 
3507 TEST(TransferTest, AssignMemberBeforeCopy) {
3508   std::string Code = R"(
3509     struct A {
3510       int Foo;
3511     };
3512 
3513     void target() {
3514       A A1;
3515       A A2;
3516       int Bar;
3517       A1.Foo = Bar;
3518       A2 = A1;
3519       // [[p]]
3520     }
3521   )";
3522   runDataflow(
3523       Code,
3524       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3525          ASTContext &ASTCtx) {
3526         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3527         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3528 
3529         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3530         ASSERT_THAT(FooDecl, NotNull());
3531 
3532         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3533         ASSERT_THAT(BarDecl, NotNull());
3534 
3535         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3536         ASSERT_THAT(A1Decl, NotNull());
3537 
3538         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3539         ASSERT_THAT(A2Decl, NotNull());
3540 
3541         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3542 
3543         const auto *A2Val = cast<RecordValue>(Env.getValue(*A2Decl));
3544         EXPECT_EQ(getFieldValue(A2Val, *FooDecl, Env), BarVal);
3545       });
3546 }
3547 
3548 TEST(TransferTest, BooleanEquality) {
3549   std::string Code = R"(
3550     void target(bool Bar) {
3551       bool Foo = true;
3552       if (Bar == Foo) {
3553         (void)0;
3554         /*[[p-then]]*/
3555       } else {
3556         (void)0;
3557         /*[[p-else]]*/
3558       }
3559     }
3560   )";
3561   runDataflow(
3562       Code,
3563       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3564          ASTContext &ASTCtx) {
3565         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3566         const Environment &EnvThen =
3567             getEnvironmentAtAnnotation(Results, "p-then");
3568         const Environment &EnvElse =
3569             getEnvironmentAtAnnotation(Results, "p-else");
3570 
3571         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3572         ASSERT_THAT(BarDecl, NotNull());
3573 
3574         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3575         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3576 
3577         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3578         EXPECT_TRUE(
3579             EnvElse.flowConditionImplies(EnvElse.arena().makeNot(BarValElse)));
3580       });
3581 }
3582 
3583 TEST(TransferTest, BooleanInequality) {
3584   std::string Code = R"(
3585     void target(bool Bar) {
3586       bool Foo = true;
3587       if (Bar != Foo) {
3588         (void)0;
3589         /*[[p-then]]*/
3590       } else {
3591         (void)0;
3592         /*[[p-else]]*/
3593       }
3594     }
3595   )";
3596   runDataflow(
3597       Code,
3598       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3599          ASTContext &ASTCtx) {
3600         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3601         const Environment &EnvThen =
3602             getEnvironmentAtAnnotation(Results, "p-then");
3603         const Environment &EnvElse =
3604             getEnvironmentAtAnnotation(Results, "p-else");
3605 
3606         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3607         ASSERT_THAT(BarDecl, NotNull());
3608 
3609         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3610         EXPECT_TRUE(
3611             EnvThen.flowConditionImplies(EnvThen.arena().makeNot(BarValThen)));
3612 
3613         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3614         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3615       });
3616 }
3617 
3618 TEST(TransferTest, IntegerLiteralEquality) {
3619   std::string Code = R"(
3620     void target() {
3621       bool equal = (42 == 42);
3622       // [[p]]
3623     }
3624   )";
3625   runDataflow(
3626       Code,
3627       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3628          ASTContext &ASTCtx) {
3629         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3630 
3631         auto &Equal =
3632             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
3633         EXPECT_TRUE(Env.flowConditionImplies(Equal));
3634       });
3635 }
3636 
3637 TEST(TransferTest, CorrelatedBranches) {
3638   std::string Code = R"(
3639     void target(bool B, bool C) {
3640       if (B) {
3641         return;
3642       }
3643       (void)0;
3644       /*[[p0]]*/
3645       if (C) {
3646         B = true;
3647         /*[[p1]]*/
3648       }
3649       if (B) {
3650         (void)0;
3651         /*[[p2]]*/
3652       }
3653     }
3654   )";
3655   runDataflow(
3656       Code,
3657       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3658          ASTContext &ASTCtx) {
3659         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3660 
3661         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3662         ASSERT_THAT(CDecl, NotNull());
3663 
3664         {
3665           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3666           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3667           ASSERT_THAT(BDecl, NotNull());
3668           auto &BVal = getFormula(*BDecl, Env);
3669 
3670           EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BVal)));
3671         }
3672 
3673         {
3674           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3675           auto &CVal = getFormula(*CDecl, Env);
3676           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3677         }
3678 
3679         {
3680           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3681           auto &CVal = getFormula(*CDecl, Env);
3682           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3683         }
3684       });
3685 }
3686 
3687 TEST(TransferTest, LoopWithAssignmentConverges) {
3688   std::string Code = R"(
3689     bool foo();
3690 
3691     void target() {
3692        do {
3693         bool Bar = foo();
3694         if (Bar) break;
3695         (void)Bar;
3696         /*[[p]]*/
3697       } while (true);
3698     }
3699   )";
3700   // The key property that we are verifying is implicit in `runDataflow` --
3701   // namely, that the analysis succeeds, rather than hitting the maximum number
3702   // of iterations.
3703   runDataflow(
3704       Code,
3705       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3706          ASTContext &ASTCtx) {
3707         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3708         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3709 
3710         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3711         ASSERT_THAT(BarDecl, NotNull());
3712 
3713         auto &BarVal = getFormula(*BarDecl, Env);
3714         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
3715       });
3716 }
3717 
3718 TEST(TransferTest, LoopWithStagedAssignments) {
3719   std::string Code = R"(
3720     bool foo();
3721 
3722     void target() {
3723       bool Bar = false;
3724       bool Err = false;
3725       while (foo()) {
3726         if (Bar)
3727           Err = true;
3728         Bar = true;
3729         /*[[p]]*/
3730       }
3731     }
3732   )";
3733   runDataflow(
3734       Code,
3735       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3736          ASTContext &ASTCtx) {
3737         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3738         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3739 
3740         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3741         ASSERT_THAT(BarDecl, NotNull());
3742         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3743         ASSERT_THAT(ErrDecl, NotNull());
3744 
3745         auto &BarVal = getFormula(*BarDecl, Env);
3746         auto &ErrVal = getFormula(*ErrDecl, Env);
3747         EXPECT_TRUE(Env.flowConditionImplies(BarVal));
3748         // An unsound analysis, for example only evaluating the loop once, can
3749         // conclude that `Err` is false. So, we test that this conclusion is not
3750         // reached.
3751         EXPECT_FALSE(
3752             Env.flowConditionImplies(Env.arena().makeNot(ErrVal)));
3753       });
3754 }
3755 
3756 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3757   std::string Code = R"(
3758     bool &foo();
3759 
3760     void target() {
3761        do {
3762         bool& Bar = foo();
3763         if (Bar) break;
3764         (void)Bar;
3765         /*[[p]]*/
3766       } while (true);
3767     }
3768   )";
3769   // The key property that we are verifying is that the analysis succeeds,
3770   // rather than hitting the maximum number of iterations.
3771   runDataflow(
3772       Code,
3773       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3774          ASTContext &ASTCtx) {
3775         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3776         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3777 
3778         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3779         ASSERT_THAT(BarDecl, NotNull());
3780 
3781         auto &BarVal = getFormula(*BarDecl, Env);
3782         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
3783       });
3784 }
3785 
3786 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3787   std::string Code = R"(
3788     struct Lookup {
3789       int x;
3790     };
3791 
3792     void target(Lookup val, bool b) {
3793       const Lookup* l = nullptr;
3794       while (b) {
3795         l = &val;
3796         /*[[p-inner]]*/
3797       }
3798       (void)0;
3799       /*[[p-outer]]*/
3800     }
3801   )";
3802   // The key property that we are verifying is implicit in `runDataflow` --
3803   // namely, that the analysis succeeds, rather than hitting the maximum number
3804   // of iterations.
3805   runDataflow(
3806       Code,
3807       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3808          ASTContext &ASTCtx) {
3809         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
3810         const Environment &InnerEnv =
3811             getEnvironmentAtAnnotation(Results, "p-inner");
3812         const Environment &OuterEnv =
3813             getEnvironmentAtAnnotation(Results, "p-outer");
3814 
3815         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3816         ASSERT_THAT(ValDecl, NotNull());
3817 
3818         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3819         ASSERT_THAT(LDecl, NotNull());
3820 
3821         // Inner.
3822         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
3823         ASSERT_THAT(LVal, NotNull());
3824 
3825         EXPECT_EQ(&LVal->getPointeeLoc(),
3826                   InnerEnv.getStorageLocation(*ValDecl));
3827 
3828         // Outer.
3829         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
3830         ASSERT_THAT(LVal, NotNull());
3831 
3832         // The loop body may not have been executed, so we should not conclude
3833         // that `l` points to `val`.
3834         EXPECT_NE(&LVal->getPointeeLoc(),
3835                   OuterEnv.getStorageLocation(*ValDecl));
3836       });
3837 }
3838 
3839 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
3840   std::string Code = R"cc(
3841     bool some_condition();
3842 
3843     void target(int i1, int i2) {
3844       int *p = &i1;
3845       while (true) {
3846         (void)*p;
3847         if (some_condition())
3848           p = &i1;
3849         else
3850           p = &i2;
3851       }
3852     }
3853   )cc";
3854   // FIXME: Implement pointer value widening to make analysis converge.
3855   ASSERT_THAT_ERROR(
3856       checkDataflowWithNoopAnalysis(Code),
3857       llvm::FailedWithMessage("maximum number of iterations reached"));
3858 }
3859 
3860 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
3861   std::string Code = R"cc(
3862     struct Lookup {
3863       int x;
3864     };
3865 
3866     bool some_condition();
3867 
3868     void target(Lookup l1, Lookup l2) {
3869       Lookup *l = &l1;
3870       while (true) {
3871         (void)l->x;
3872         if (some_condition())
3873           l = &l1;
3874         else
3875           l = &l2;
3876       }
3877     }
3878   )cc";
3879   // FIXME: Implement pointer value widening to make analysis converge.
3880   ASSERT_THAT_ERROR(
3881       checkDataflowWithNoopAnalysis(Code),
3882       llvm::FailedWithMessage("maximum number of iterations reached"));
3883 }
3884 
3885 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
3886   std::string Code = R"(
3887     union Union {
3888       int A;
3889       float B;
3890     };
3891 
3892     void foo() {
3893       Union A;
3894       Union B;
3895       A = B;
3896     }
3897   )";
3898   // This is a crash regression test when calling the transfer function on a
3899   // `CXXThisExpr` that refers to a union.
3900   runDataflow(
3901       Code,
3902       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3903          ASTContext &) {},
3904       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3905 }
3906 
3907 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3908   std::string Code = R"(
3909     struct A {
3910       int Foo;
3911       int Bar;
3912     };
3913 
3914     void target() {
3915       int Qux;
3916       A Baz;
3917       Baz.Foo = Qux;
3918       auto &FooRef = Baz.Foo;
3919       auto &BarRef = Baz.Bar;
3920       auto &[BoundFooRef, BoundBarRef] = Baz;
3921       // [[p]]
3922     }
3923   )";
3924   runDataflow(
3925       Code,
3926       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3927          ASTContext &ASTCtx) {
3928         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3929         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3930 
3931         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3932         ASSERT_THAT(FooRefDecl, NotNull());
3933 
3934         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3935         ASSERT_THAT(BarRefDecl, NotNull());
3936 
3937         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3938         ASSERT_THAT(QuxDecl, NotNull());
3939 
3940         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3941         ASSERT_THAT(BoundFooRefDecl, NotNull());
3942 
3943         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3944         ASSERT_THAT(BoundBarRefDecl, NotNull());
3945 
3946         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3947         ASSERT_THAT(FooRefLoc, NotNull());
3948 
3949         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3950         ASSERT_THAT(BarRefLoc, NotNull());
3951 
3952         const Value *QuxVal = Env.getValue(*QuxDecl);
3953         ASSERT_THAT(QuxVal, NotNull());
3954 
3955         const StorageLocation *BoundFooRefLoc =
3956             Env.getStorageLocation(*BoundFooRefDecl);
3957         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3958 
3959         const StorageLocation *BoundBarRefLoc =
3960             Env.getStorageLocation(*BoundBarRefDecl);
3961         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3962 
3963         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
3964       });
3965 }
3966 
3967 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3968   std::string Code = R"(
3969     struct A {
3970       int &Foo;
3971       int &Bar;
3972     };
3973 
3974     void target(A Baz) {
3975       int Qux;
3976       Baz.Foo = Qux;
3977       auto &FooRef = Baz.Foo;
3978       auto &BarRef = Baz.Bar;
3979       auto &[BoundFooRef, BoundBarRef] = Baz;
3980       // [[p]]
3981     }
3982   )";
3983   runDataflow(
3984       Code,
3985       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3986          ASTContext &ASTCtx) {
3987         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3988         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3989 
3990         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3991         ASSERT_THAT(FooRefDecl, NotNull());
3992 
3993         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3994         ASSERT_THAT(BarRefDecl, NotNull());
3995 
3996         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3997         ASSERT_THAT(QuxDecl, NotNull());
3998 
3999         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4000         ASSERT_THAT(BoundFooRefDecl, NotNull());
4001 
4002         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4003         ASSERT_THAT(BoundBarRefDecl, NotNull());
4004 
4005         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4006         ASSERT_THAT(FooRefLoc, NotNull());
4007 
4008         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4009         ASSERT_THAT(BarRefLoc, NotNull());
4010 
4011         const Value *QuxVal = Env.getValue(*QuxDecl);
4012         ASSERT_THAT(QuxVal, NotNull());
4013 
4014         const StorageLocation *BoundFooRefLoc =
4015             Env.getStorageLocation(*BoundFooRefDecl);
4016         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4017 
4018         const StorageLocation *BoundBarRefLoc =
4019             Env.getStorageLocation(*BoundBarRefDecl);
4020         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4021 
4022         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4023       });
4024 }
4025 
4026 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4027   std::string Code = R"(
4028     struct A {
4029       int Foo;
4030       int Bar;
4031     };
4032 
4033     void target() {
4034       int Qux;
4035       A Baz;
4036       Baz.Foo = Qux;
4037       auto &FooRef = Baz.Foo;
4038       auto &BarRef = Baz.Bar;
4039       auto [BoundFoo, BoundBar] = Baz;
4040       // [[p]]
4041     }
4042   )";
4043   runDataflow(
4044       Code,
4045       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4046          ASTContext &ASTCtx) {
4047         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4048         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4049 
4050         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4051         ASSERT_THAT(FooRefDecl, NotNull());
4052 
4053         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4054         ASSERT_THAT(BarRefDecl, NotNull());
4055 
4056         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4057         ASSERT_THAT(BoundFooDecl, NotNull());
4058 
4059         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4060         ASSERT_THAT(BoundBarDecl, NotNull());
4061 
4062         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4063         ASSERT_THAT(QuxDecl, NotNull());
4064 
4065         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4066         ASSERT_THAT(FooRefLoc, NotNull());
4067 
4068         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4069         ASSERT_THAT(BarRefLoc, NotNull());
4070 
4071         const Value *QuxVal = Env.getValue(*QuxDecl);
4072         ASSERT_THAT(QuxVal, NotNull());
4073 
4074         const StorageLocation *BoundFooLoc =
4075             Env.getStorageLocation(*BoundFooDecl);
4076         EXPECT_NE(BoundFooLoc, FooRefLoc);
4077 
4078         const StorageLocation *BoundBarLoc =
4079             Env.getStorageLocation(*BoundBarDecl);
4080         EXPECT_NE(BoundBarLoc, BarRefLoc);
4081 
4082         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4083       });
4084 }
4085 
4086 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4087   std::string Code = R"(
4088     namespace std {
4089     using size_t = int;
4090     template <class> struct tuple_size;
4091     template <std::size_t, class> struct tuple_element;
4092     template <class...> class tuple;
4093 
4094     namespace {
4095     template <class T, T v>
4096     struct size_helper { static const T value = v; };
4097     } // namespace
4098 
4099     template <class... T>
4100     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4101 
4102     template <std::size_t I, class... T>
4103     struct tuple_element<I, tuple<T...>> {
4104       using type =  __type_pack_element<I, T...>;
4105     };
4106 
4107     template <class...> class tuple {};
4108 
4109     template <std::size_t I, class... T>
4110     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4111     } // namespace std
4112 
4113     std::tuple<bool, int> makeTuple();
4114 
4115     void target(bool B) {
4116       auto [BoundFoo, BoundBar] = makeTuple();
4117       bool Baz;
4118       // Include if-then-else to test interaction of `BindingDecl` with join.
4119       if (B) {
4120         Baz = BoundFoo;
4121         (void)BoundBar;
4122         // [[p1]]
4123       } else {
4124         Baz = BoundFoo;
4125       }
4126       (void)0;
4127       // [[p2]]
4128     }
4129   )";
4130   runDataflow(
4131       Code,
4132       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4133          ASTContext &ASTCtx) {
4134         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4135         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4136 
4137         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4138         ASSERT_THAT(BoundFooDecl, NotNull());
4139 
4140         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4141         ASSERT_THAT(BoundBarDecl, NotNull());
4142 
4143         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4144         ASSERT_THAT(BazDecl, NotNull());
4145 
4146         // BindingDecls always map to references -- either lvalue or rvalue, so
4147         // we still need to skip here.
4148         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4149         ASSERT_THAT(BoundFooValue, NotNull());
4150         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4151 
4152         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4153         ASSERT_THAT(BoundBarValue, NotNull());
4154         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4155 
4156         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4157         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4158 
4159         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4160 
4161         // Test that `BoundFooDecl` retains the value we expect, after the join.
4162         BoundFooValue = Env2.getValue(*BoundFooDecl);
4163         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4164       });
4165 }
4166 
4167 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4168   std::string Code = R"(
4169     namespace std {
4170     using size_t = int;
4171     template <class> struct tuple_size;
4172     template <std::size_t, class> struct tuple_element;
4173     template <class...> class tuple;
4174 
4175     namespace {
4176     template <class T, T v>
4177     struct size_helper { static const T value = v; };
4178     } // namespace
4179 
4180     template <class... T>
4181     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4182 
4183     template <std::size_t I, class... T>
4184     struct tuple_element<I, tuple<T...>> {
4185       using type =  __type_pack_element<I, T...>;
4186     };
4187 
4188     template <class...> class tuple {};
4189 
4190     template <std::size_t I, class... T>
4191     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4192     } // namespace std
4193 
4194     std::tuple<bool, int> &getTuple();
4195 
4196     void target(bool B) {
4197       auto &[BoundFoo, BoundBar] = getTuple();
4198       bool Baz;
4199       // Include if-then-else to test interaction of `BindingDecl` with join.
4200       if (B) {
4201         Baz = BoundFoo;
4202         (void)BoundBar;
4203         // [[p1]]
4204       } else {
4205         Baz = BoundFoo;
4206       }
4207       (void)0;
4208       // [[p2]]
4209     }
4210   )";
4211   runDataflow(
4212       Code,
4213       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4214          ASTContext &ASTCtx) {
4215         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4216         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4217 
4218         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4219         ASSERT_THAT(BoundFooDecl, NotNull());
4220 
4221         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4222         ASSERT_THAT(BoundBarDecl, NotNull());
4223 
4224         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4225         ASSERT_THAT(BazDecl, NotNull());
4226 
4227         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4228         ASSERT_THAT(BoundFooValue, NotNull());
4229         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4230 
4231         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4232         ASSERT_THAT(BoundBarValue, NotNull());
4233         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4234 
4235         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4236         // works as expected. We don't test aliasing properties of the
4237         // reference, because we don't model `std::get` and so have no way to
4238         // equate separate references into the tuple.
4239         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4240 
4241         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4242 
4243         // Test that `BoundFooDecl` retains the value we expect, after the join.
4244         BoundFooValue = Env2.getValue(*BoundFooDecl);
4245         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4246       });
4247 }
4248 
4249 TEST(TransferTest, BinaryOperatorComma) {
4250   std::string Code = R"(
4251     void target(int Foo, int Bar) {
4252       int &Baz = (Foo, Bar);
4253       // [[p]]
4254     }
4255   )";
4256   runDataflow(
4257       Code,
4258       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4259          ASTContext &ASTCtx) {
4260         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4261         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4262 
4263         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4264         ASSERT_THAT(BarDecl, NotNull());
4265 
4266         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4267         ASSERT_THAT(BazDecl, NotNull());
4268 
4269         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4270         ASSERT_THAT(BarLoc, NotNull());
4271 
4272         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4273         EXPECT_EQ(BazLoc, BarLoc);
4274       });
4275 }
4276 
4277 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4278   std::string Code = R"(
4279     void target(bool Foo) {
4280       if (Foo) {
4281         (void)0;
4282         // [[if_then]]
4283       } else {
4284         (void)0;
4285         // [[if_else]]
4286       }
4287     }
4288   )";
4289   runDataflow(
4290       Code,
4291       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4292          ASTContext &ASTCtx) {
4293         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4294         const Environment &ThenEnv =
4295             getEnvironmentAtAnnotation(Results, "if_then");
4296         const Environment &ElseEnv =
4297             getEnvironmentAtAnnotation(Results, "if_else");
4298 
4299         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4300         ASSERT_THAT(FooDecl, NotNull());
4301 
4302         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
4303         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
4304 
4305         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
4306         EXPECT_TRUE(
4307             ElseEnv.flowConditionImplies(ElseEnv.arena().makeNot(ElseFooVal)));
4308       });
4309 }
4310 
4311 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4312   std::string Code = R"(
4313     void target(bool Foo) {
4314       while (Foo) {
4315         (void)0;
4316         // [[loop_body]]
4317       }
4318       (void)0;
4319       // [[after_loop]]
4320     }
4321   )";
4322   runDataflow(
4323       Code,
4324       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4325          ASTContext &ASTCtx) {
4326         ASSERT_THAT(Results.keys(),
4327                     UnorderedElementsAre("loop_body", "after_loop"));
4328         const Environment &LoopBodyEnv =
4329             getEnvironmentAtAnnotation(Results, "loop_body");
4330         const Environment &AfterLoopEnv =
4331             getEnvironmentAtAnnotation(Results, "after_loop");
4332 
4333         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4334         ASSERT_THAT(FooDecl, NotNull());
4335 
4336         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
4337         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4338 
4339         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4340         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4341             AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4342       });
4343 }
4344 
4345 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4346   std::string Code = R"(
4347     void target(bool Foo) {
4348       bool Bar = true;
4349       do {
4350         (void)0;
4351         // [[loop_body]]
4352         Bar = false;
4353       } while (Foo);
4354       (void)0;
4355       // [[after_loop]]
4356     }
4357   )";
4358   runDataflow(
4359       Code,
4360       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4361          ASTContext &ASTCtx) {
4362         ASSERT_THAT(Results.keys(),
4363                     UnorderedElementsAre("loop_body", "after_loop"));
4364         const Environment &LoopBodyEnv =
4365             getEnvironmentAtAnnotation(Results, "loop_body");
4366         const Environment &AfterLoopEnv =
4367             getEnvironmentAtAnnotation(Results, "after_loop");
4368         auto &A = AfterLoopEnv.arena();
4369 
4370         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4371         ASSERT_THAT(FooDecl, NotNull());
4372 
4373         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4374         ASSERT_THAT(BarDecl, NotNull());
4375 
4376         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4377         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
4378         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
4379             A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4380 
4381         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4382         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
4383         EXPECT_TRUE(
4384             AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopFooVal)));
4385         EXPECT_TRUE(
4386             AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopBarVal)));
4387       });
4388 }
4389 
4390 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4391   std::string Code = R"(
4392     void target(bool Foo) {
4393       for (; Foo;) {
4394         (void)0;
4395         // [[loop_body]]
4396       }
4397       (void)0;
4398       // [[after_loop]]
4399     }
4400   )";
4401   runDataflow(
4402       Code,
4403       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4404          ASTContext &ASTCtx) {
4405         ASSERT_THAT(Results.keys(),
4406                     UnorderedElementsAre("loop_body", "after_loop"));
4407         const Environment &LoopBodyEnv =
4408             getEnvironmentAtAnnotation(Results, "loop_body");
4409         const Environment &AfterLoopEnv =
4410             getEnvironmentAtAnnotation(Results, "after_loop");
4411 
4412         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4413         ASSERT_THAT(FooDecl, NotNull());
4414 
4415         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4416         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4417 
4418         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4419         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4420             AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4421       });
4422 }
4423 
4424 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4425   std::string Code = R"(
4426     void target(bool Foo) {
4427       for (;;) {
4428         (void)0;
4429         // [[loop_body]]
4430       }
4431     }
4432   )";
4433   runDataflow(
4434       Code,
4435       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4436          ASTContext &ASTCtx) {
4437         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4438         const Environment &LoopBodyEnv =
4439             getEnvironmentAtAnnotation(Results, "loop_body");
4440 
4441         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4442         ASSERT_THAT(FooDecl, NotNull());
4443 
4444         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4445         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4446       });
4447 }
4448 
4449 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4450   std::string Code = R"(
4451     bool GiveBool();
4452     void SetBool(bool &Var) { Var = true; }
4453 
4454     void target() {
4455       bool Foo = GiveBool();
4456       SetBool(Foo);
4457       // [[p]]
4458     }
4459   )";
4460   runDataflow(
4461       Code,
4462       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4463          ASTContext &ASTCtx) {
4464         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4465         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4466 
4467         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4468         ASSERT_THAT(FooDecl, NotNull());
4469 
4470         auto &FooVal = getFormula(*FooDecl, Env);
4471         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4472         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4473       },
4474       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4475 }
4476 
4477 TEST(TransferTest, ContextSensitiveReturnReference) {
4478   std::string Code = R"(
4479     class S {};
4480     S& target(bool b, S &s) {
4481       return s;
4482       // [[p]]
4483     }
4484   )";
4485   runDataflow(
4486       Code,
4487       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4488          ASTContext &ASTCtx) {
4489         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4490 
4491         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4492         ASSERT_THAT(SDecl, NotNull());
4493 
4494         auto *SLoc = Env.getStorageLocation(*SDecl);
4495         ASSERT_THAT(SLoc, NotNull());
4496 
4497         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4498       },
4499       {BuiltinOptions{ContextSensitiveOptions{}}});
4500 }
4501 
4502 // This test is a regression test, based on a real crash.
4503 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4504   std::string Code = R"(
4505     class S {};
4506     S& target(bool b, S &s) {
4507       return b ? s : s;
4508       // [[p]]
4509     }
4510   )";
4511   runDataflow(
4512       Code,
4513       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4514          ASTContext &ASTCtx) {
4515         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4516         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4517 
4518         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4519         ASSERT_THAT(SDecl, NotNull());
4520 
4521         auto *SLoc = Env.getStorageLocation(*SDecl);
4522         ASSERT_THAT(SLoc, NotNull());
4523         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4524 
4525         auto *Loc = Env.getReturnStorageLocation();
4526         ASSERT_THAT(Loc, NotNull());
4527         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4528 
4529         // TODO: We would really like to make this stronger assertion, but that
4530         // doesn't work because we don't propagate values correctly through
4531         // the conditional operator yet.
4532         // ASSERT_THAT(Loc, Eq(SLoc));
4533       },
4534       {BuiltinOptions{ContextSensitiveOptions{}}});
4535 }
4536 
4537 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4538   std::string Code = R"(
4539     class S {};
4540     S &callee(bool b, S &s1_parm, S &s2_parm) {
4541       if (b)
4542         return s1_parm;
4543       else
4544         return s2_parm;
4545     }
4546     void target(bool b) {
4547       S s1;
4548       S s2;
4549       S &return_s1 = s1;
4550       S &return_s2 = s2;
4551       S &return_dont_know = callee(b, s1, s2);
4552       // [[p]]
4553     }
4554   )";
4555   runDataflow(
4556       Code,
4557       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4558          ASTContext &ASTCtx) {
4559         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4560 
4561         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4562         ASSERT_THAT(S1, NotNull());
4563         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4564         ASSERT_THAT(S2, NotNull());
4565         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4566         ASSERT_THAT(ReturnS1, NotNull());
4567         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4568         ASSERT_THAT(ReturnS2, NotNull());
4569         const ValueDecl *ReturnDontKnow =
4570             findValueDecl(ASTCtx, "return_dont_know");
4571         ASSERT_THAT(ReturnDontKnow, NotNull());
4572 
4573         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4574         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4575 
4576         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4577         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4578 
4579         // In the case where we don't have a consistent storage location for
4580         // the return value, the framework creates a new storage location, which
4581         // should be different from the storage locations of `s1` and `s2`.
4582         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4583         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4584       },
4585       {BuiltinOptions{ContextSensitiveOptions{}}});
4586 }
4587 
4588 TEST(TransferTest, ContextSensitiveDepthZero) {
4589   std::string Code = R"(
4590     bool GiveBool();
4591     void SetBool(bool &Var) { Var = true; }
4592 
4593     void target() {
4594       bool Foo = GiveBool();
4595       SetBool(Foo);
4596       // [[p]]
4597     }
4598   )";
4599   runDataflow(
4600       Code,
4601       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4602          ASTContext &ASTCtx) {
4603         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4604         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4605 
4606         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4607         ASSERT_THAT(FooDecl, NotNull());
4608 
4609         auto &FooVal = getFormula(*FooDecl, Env);
4610         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4611         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4612       },
4613       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4614 }
4615 
4616 TEST(TransferTest, ContextSensitiveSetTrue) {
4617   std::string Code = R"(
4618     bool GiveBool();
4619     void SetBool(bool &Var) { Var = true; }
4620 
4621     void target() {
4622       bool Foo = GiveBool();
4623       SetBool(Foo);
4624       // [[p]]
4625     }
4626   )";
4627   runDataflow(
4628       Code,
4629       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4630          ASTContext &ASTCtx) {
4631         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4632         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4633 
4634         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4635         ASSERT_THAT(FooDecl, NotNull());
4636 
4637         auto &FooVal = getFormula(*FooDecl, Env);
4638         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4639       },
4640       {BuiltinOptions{ContextSensitiveOptions{}}});
4641 }
4642 
4643 TEST(TransferTest, ContextSensitiveSetFalse) {
4644   std::string Code = R"(
4645     bool GiveBool();
4646     void SetBool(bool &Var) { Var = false; }
4647 
4648     void target() {
4649       bool Foo = GiveBool();
4650       SetBool(Foo);
4651       // [[p]]
4652     }
4653   )";
4654   runDataflow(
4655       Code,
4656       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4657          ASTContext &ASTCtx) {
4658         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4659         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4660 
4661         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4662         ASSERT_THAT(FooDecl, NotNull());
4663 
4664         auto &FooVal = getFormula(*FooDecl, Env);
4665         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4666       },
4667       {BuiltinOptions{ContextSensitiveOptions{}}});
4668 }
4669 
4670 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4671   std::string Code = R"(
4672     bool GiveBool();
4673     void SetBool(bool &Var, bool Val) { Var = Val; }
4674 
4675     void target() {
4676       bool Foo = GiveBool();
4677       bool Bar = GiveBool();
4678       SetBool(Foo, true);
4679       SetBool(Bar, false);
4680       // [[p]]
4681     }
4682   )";
4683   runDataflow(
4684       Code,
4685       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4686          ASTContext &ASTCtx) {
4687         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4688         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4689         auto &A = Env.arena();
4690 
4691         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4692         ASSERT_THAT(FooDecl, NotNull());
4693 
4694         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4695         ASSERT_THAT(BarDecl, NotNull());
4696 
4697         auto &FooVal = getFormula(*FooDecl, Env);
4698         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4699         EXPECT_FALSE(Env.flowConditionImplies(A.makeNot(FooVal)));
4700 
4701         auto &BarVal = getFormula(*BarDecl, Env);
4702         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4703         EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(BarVal)));
4704       },
4705       {BuiltinOptions{ContextSensitiveOptions{}}});
4706 }
4707 
4708 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4709   std::string Code = R"(
4710     bool GiveBool();
4711     void SetBool1(bool &Var) { Var = true; }
4712     void SetBool2(bool &Var) { SetBool1(Var); }
4713 
4714     void target() {
4715       bool Foo = GiveBool();
4716       SetBool2(Foo);
4717       // [[p]]
4718     }
4719   )";
4720   runDataflow(
4721       Code,
4722       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4723          ASTContext &ASTCtx) {
4724         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4725         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4726 
4727         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4728         ASSERT_THAT(FooDecl, NotNull());
4729 
4730         auto &FooVal = getFormula(*FooDecl, Env);
4731         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4732         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4733       },
4734       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4735 }
4736 
4737 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4738   std::string Code = R"(
4739     bool GiveBool();
4740     void SetBool1(bool &Var) { Var = true; }
4741     void SetBool2(bool &Var) { SetBool1(Var); }
4742 
4743     void target() {
4744       bool Foo = GiveBool();
4745       SetBool2(Foo);
4746       // [[p]]
4747     }
4748   )";
4749   runDataflow(
4750       Code,
4751       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4752          ASTContext &ASTCtx) {
4753         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4754         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4755 
4756         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4757         ASSERT_THAT(FooDecl, NotNull());
4758 
4759         auto &FooVal = getFormula(*FooDecl, Env);
4760         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4761       },
4762       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4763 }
4764 
4765 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4766   std::string Code = R"(
4767     bool GiveBool();
4768     void SetBool1(bool &Var) { Var = true; }
4769     void SetBool2(bool &Var) { SetBool1(Var); }
4770     void SetBool3(bool &Var) { SetBool2(Var); }
4771 
4772     void target() {
4773       bool Foo = GiveBool();
4774       SetBool3(Foo);
4775       // [[p]]
4776     }
4777   )";
4778   runDataflow(
4779       Code,
4780       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4781          ASTContext &ASTCtx) {
4782         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4783         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4784 
4785         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4786         ASSERT_THAT(FooDecl, NotNull());
4787 
4788         auto &FooVal = getFormula(*FooDecl, Env);
4789         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4790         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4791       },
4792       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4793 }
4794 
4795 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4796   std::string Code = R"(
4797     bool GiveBool();
4798     void SetBool1(bool &Var) { Var = true; }
4799     void SetBool2(bool &Var) { SetBool1(Var); }
4800     void SetBool3(bool &Var) { SetBool2(Var); }
4801 
4802     void target() {
4803       bool Foo = GiveBool();
4804       SetBool3(Foo);
4805       // [[p]]
4806     }
4807   )";
4808   runDataflow(
4809       Code,
4810       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4811          ASTContext &ASTCtx) {
4812         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4813         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4814 
4815         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4816         ASSERT_THAT(FooDecl, NotNull());
4817 
4818         auto &FooVal = getFormula(*FooDecl, Env);
4819         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4820       },
4821       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
4822 }
4823 
4824 TEST(TransferTest, ContextSensitiveMutualRecursion) {
4825   std::string Code = R"(
4826     bool Pong(bool X, bool Y);
4827 
4828     bool Ping(bool X, bool Y) {
4829       if (X) {
4830         return Y;
4831       } else {
4832         return Pong(!X, Y);
4833       }
4834     }
4835 
4836     bool Pong(bool X, bool Y) {
4837       if (Y) {
4838         return X;
4839       } else {
4840         return Ping(X, !Y);
4841       }
4842     }
4843 
4844     void target() {
4845       bool Foo = Ping(false, false);
4846       // [[p]]
4847     }
4848   )";
4849   runDataflow(
4850       Code,
4851       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4852          ASTContext &ASTCtx) {
4853         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4854         // The analysis doesn't crash...
4855         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4856 
4857         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4858         ASSERT_THAT(FooDecl, NotNull());
4859 
4860         auto &FooVal = getFormula(*FooDecl, Env);
4861         // ... but it also can't prove anything here.
4862         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4863         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4864       },
4865       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
4866 }
4867 
4868 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
4869   std::string Code = R"(
4870     void SetBools(bool &Var1, bool &Var2) {
4871       Var1 = true;
4872       Var2 = false;
4873     }
4874 
4875     void target() {
4876       bool Foo = false;
4877       bool Bar = true;
4878       SetBools(Foo, Bar);
4879       // [[p]]
4880     }
4881   )";
4882   runDataflow(
4883       Code,
4884       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4885          ASTContext &ASTCtx) {
4886         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4887         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4888 
4889         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4890         ASSERT_THAT(FooDecl, NotNull());
4891 
4892         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4893         ASSERT_THAT(BarDecl, NotNull());
4894 
4895         auto &FooVal = getFormula(*FooDecl, Env);
4896         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4897         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4898 
4899         auto &BarVal = getFormula(*BarDecl, Env);
4900         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4901         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
4902       },
4903       {BuiltinOptions{ContextSensitiveOptions{}}});
4904 }
4905 
4906 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
4907   std::string Code = R"(
4908     void IfCond(bool Cond, bool &Then, bool &Else) {
4909       if (Cond) {
4910         Then = true;
4911       } else {
4912         Else = true;
4913       }
4914     }
4915 
4916     void target() {
4917       bool Foo = false;
4918       bool Bar = false;
4919       bool Baz = false;
4920       IfCond(Foo, Bar, Baz);
4921       // [[p]]
4922     }
4923   )";
4924   runDataflow(
4925       Code,
4926       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4927          ASTContext &ASTCtx) {
4928         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4929         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4930 
4931         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4932         ASSERT_THAT(BarDecl, NotNull());
4933 
4934         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4935         ASSERT_THAT(BazDecl, NotNull());
4936 
4937         auto &BarVal = getFormula(*BarDecl, Env);
4938         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4939         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
4940 
4941         auto &BazVal = getFormula(*BazDecl, Env);
4942         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4943         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(BazVal)));
4944       },
4945       {BuiltinOptions{ContextSensitiveOptions{}}});
4946 }
4947 
4948 TEST(TransferTest, ContextSensitiveReturnVoid) {
4949   std::string Code = R"(
4950     void Noop() { return; }
4951 
4952     void target() {
4953       Noop();
4954       // [[p]]
4955     }
4956   )";
4957   runDataflow(
4958       Code,
4959       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4960          ASTContext &ASTCtx) {
4961         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4962         // This just tests that the analysis doesn't crash.
4963       },
4964       {BuiltinOptions{ContextSensitiveOptions{}}});
4965 }
4966 
4967 TEST(TransferTest, ContextSensitiveReturnTrue) {
4968   std::string Code = R"(
4969     bool GiveBool() { return true; }
4970 
4971     void target() {
4972       bool Foo = GiveBool();
4973       // [[p]]
4974     }
4975   )";
4976   runDataflow(
4977       Code,
4978       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4979          ASTContext &ASTCtx) {
4980         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4981         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4982 
4983         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4984         ASSERT_THAT(FooDecl, NotNull());
4985 
4986         auto &FooVal = getFormula(*FooDecl, Env);
4987         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4988       },
4989       {BuiltinOptions{ContextSensitiveOptions{}}});
4990 }
4991 
4992 TEST(TransferTest, ContextSensitiveReturnFalse) {
4993   std::string Code = R"(
4994     bool GiveBool() { return false; }
4995 
4996     void target() {
4997       bool Foo = GiveBool();
4998       // [[p]]
4999     }
5000   )";
5001   runDataflow(
5002       Code,
5003       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5004          ASTContext &ASTCtx) {
5005         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5006         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5007 
5008         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5009         ASSERT_THAT(FooDecl, NotNull());
5010 
5011         auto &FooVal = getFormula(*FooDecl, Env);
5012         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
5013       },
5014       {BuiltinOptions{ContextSensitiveOptions{}}});
5015 }
5016 
5017 TEST(TransferTest, ContextSensitiveReturnArg) {
5018   std::string Code = R"(
5019     bool GiveBool();
5020     bool GiveBack(bool Arg) { return Arg; }
5021 
5022     void target() {
5023       bool Foo = GiveBool();
5024       bool Bar = GiveBack(Foo);
5025       bool Baz = Foo == Bar;
5026       // [[p]]
5027     }
5028   )";
5029   runDataflow(
5030       Code,
5031       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5032          ASTContext &ASTCtx) {
5033         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5034         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5035 
5036         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5037         ASSERT_THAT(BazDecl, NotNull());
5038 
5039         auto &BazVal = getFormula(*BazDecl, Env);
5040         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
5041       },
5042       {BuiltinOptions{ContextSensitiveOptions{}}});
5043 }
5044 
5045 TEST(TransferTest, ContextSensitiveReturnInt) {
5046   std::string Code = R"(
5047     int identity(int x) { return x; }
5048 
5049     void target() {
5050       int y = identity(42);
5051       // [[p]]
5052     }
5053   )";
5054   runDataflow(
5055       Code,
5056       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5057          ASTContext &ASTCtx) {
5058         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5059         // This just tests that the analysis doesn't crash.
5060       },
5061       {BuiltinOptions{ContextSensitiveOptions{}}});
5062 }
5063 
5064 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5065   std::string Code = R"(
5066     class MyClass {
5067     public:
5068       bool giveBool() { return true; }
5069     };
5070 
5071     void target() {
5072       MyClass MyObj;
5073       bool Foo = MyObj.giveBool();
5074       // [[p]]
5075     }
5076   )";
5077   runDataflow(
5078       Code,
5079       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5080          ASTContext &ASTCtx) {
5081         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5082         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5083 
5084         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5085         ASSERT_THAT(FooDecl, NotNull());
5086 
5087         auto &FooVal = getFormula(*FooDecl, Env);
5088         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5089       },
5090       {BuiltinOptions{ContextSensitiveOptions{}}});
5091 }
5092 
5093 TEST(TransferTest, ContextSensitiveMethodGetter) {
5094   std::string Code = R"(
5095     class MyClass {
5096     public:
5097       bool getField() { return Field; }
5098 
5099       bool Field;
5100     };
5101 
5102     void target() {
5103       MyClass MyObj;
5104       MyObj.Field = true;
5105       bool Foo = MyObj.getField();
5106       // [[p]]
5107     }
5108   )";
5109   runDataflow(
5110       Code,
5111       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5112          ASTContext &ASTCtx) {
5113         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5114         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5115 
5116         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5117         ASSERT_THAT(FooDecl, NotNull());
5118 
5119         auto &FooVal = getFormula(*FooDecl, Env);
5120         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5121       },
5122       {BuiltinOptions{ContextSensitiveOptions{}}});
5123 }
5124 
5125 TEST(TransferTest, ContextSensitiveMethodSetter) {
5126   std::string Code = R"(
5127     class MyClass {
5128     public:
5129       void setField(bool Val) { Field = Val; }
5130 
5131       bool Field;
5132     };
5133 
5134     void target() {
5135       MyClass MyObj;
5136       MyObj.setField(true);
5137       bool Foo = MyObj.Field;
5138       // [[p]]
5139     }
5140   )";
5141   runDataflow(
5142       Code,
5143       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5144          ASTContext &ASTCtx) {
5145         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5146         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5147 
5148         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5149         ASSERT_THAT(FooDecl, NotNull());
5150 
5151         auto &FooVal = getFormula(*FooDecl, Env);
5152         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5153       },
5154       {BuiltinOptions{ContextSensitiveOptions{}}});
5155 }
5156 
5157 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5158   std::string Code = R"(
5159     class MyClass {
5160     public:
5161       bool getField() { return Field; }
5162       void setField(bool Val) { Field = Val; }
5163 
5164     private:
5165       bool Field;
5166     };
5167 
5168     void target() {
5169       MyClass MyObj;
5170       MyObj.setField(true);
5171       bool Foo = MyObj.getField();
5172       // [[p]]
5173     }
5174   )";
5175   runDataflow(
5176       Code,
5177       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5178          ASTContext &ASTCtx) {
5179         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5180         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5181 
5182         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5183         ASSERT_THAT(FooDecl, NotNull());
5184 
5185         auto &FooVal = getFormula(*FooDecl, Env);
5186         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5187       },
5188       {BuiltinOptions{ContextSensitiveOptions{}}});
5189 }
5190 
5191 
5192 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5193   std::string Code = R"(
5194     class MyClass {
5195     public:
5196       void Inner() { MyField = true; }
5197       void Outer() { Inner(); }
5198 
5199       bool MyField;
5200     };
5201 
5202     void target() {
5203       MyClass MyObj;
5204       MyObj.Outer();
5205       bool Foo = MyObj.MyField;
5206       // [[p]]
5207     }
5208   )";
5209   runDataflow(
5210       Code,
5211       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5212          ASTContext &ASTCtx) {
5213         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5214         ;
5215         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5216 
5217         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5218         ASSERT_THAT(FooDecl, NotNull());
5219 
5220         auto &FooVal = getFormula(*FooDecl, Env);
5221         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5222       },
5223       {BuiltinOptions{ContextSensitiveOptions{}}});
5224 }
5225 
5226 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5227   std::string Code = R"(
5228     class MyClass {
5229     public:
5230       bool Inner() { return MyField; }
5231       bool Outer() { return Inner(); }
5232 
5233       bool MyField;
5234     };
5235 
5236     void target() {
5237       MyClass MyObj;
5238       MyObj.MyField = true;
5239       bool Foo = MyObj.Outer();
5240       // [[p]]
5241     }
5242   )";
5243   runDataflow(
5244       Code,
5245       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5246          ASTContext &ASTCtx) {
5247         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5248         ;
5249         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5250 
5251         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5252         ASSERT_THAT(FooDecl, NotNull());
5253 
5254         auto &FooVal = getFormula(*FooDecl, Env);
5255         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5256       },
5257       {BuiltinOptions{ContextSensitiveOptions{}}});
5258 }
5259 
5260 TEST(TransferTest, ContextSensitiveConstructorBody) {
5261   std::string Code = R"(
5262     class MyClass {
5263     public:
5264       MyClass() { MyField = true; }
5265 
5266       bool MyField;
5267     };
5268 
5269     void target() {
5270       MyClass MyObj;
5271       bool Foo = MyObj.MyField;
5272       // [[p]]
5273     }
5274   )";
5275   runDataflow(
5276       Code,
5277       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5278          ASTContext &ASTCtx) {
5279         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5280         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5281 
5282         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5283         ASSERT_THAT(FooDecl, NotNull());
5284 
5285         auto &FooVal = getFormula(*FooDecl, Env);
5286         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5287       },
5288       {BuiltinOptions{ContextSensitiveOptions{}}});
5289 }
5290 
5291 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5292   std::string Code = R"(
5293     class MyClass {
5294     public:
5295       MyClass() : MyField(true) {}
5296 
5297       bool MyField;
5298     };
5299 
5300     void target() {
5301       MyClass MyObj;
5302       bool Foo = MyObj.MyField;
5303       // [[p]]
5304     }
5305   )";
5306   runDataflow(
5307       Code,
5308       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5309          ASTContext &ASTCtx) {
5310         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5311         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5312 
5313         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5314         ASSERT_THAT(FooDecl, NotNull());
5315 
5316         auto &FooVal = getFormula(*FooDecl, Env);
5317         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5318       },
5319       {BuiltinOptions{ContextSensitiveOptions{}}});
5320 }
5321 
5322 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5323   std::string Code = R"(
5324     class MyClass {
5325     public:
5326       MyClass() = default;
5327 
5328       bool MyField = true;
5329     };
5330 
5331     void target() {
5332       MyClass MyObj;
5333       bool Foo = MyObj.MyField;
5334       // [[p]]
5335     }
5336   )";
5337   runDataflow(
5338       Code,
5339       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5340          ASTContext &ASTCtx) {
5341         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5342         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5343 
5344         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5345         ASSERT_THAT(FooDecl, NotNull());
5346 
5347         auto &FooVal = getFormula(*FooDecl, Env);
5348         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5349       },
5350       {BuiltinOptions{ContextSensitiveOptions{}}});
5351 }
5352 
5353 TEST(TransferTest, UnnamedBitfieldInitializer) {
5354   std::string Code = R"(
5355     struct B {};
5356     struct A {
5357       unsigned a;
5358       unsigned : 4;
5359       unsigned c;
5360       B b;
5361     };
5362     void target() {
5363       A a = {};
5364       A test = a;
5365       (void)test.c;
5366     }
5367   )";
5368   runDataflow(
5369       Code,
5370       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5371          ASTContext &ASTCtx) {
5372         // This doesn't need a body because this test was crashing the framework
5373         // before handling correctly Unnamed bitfields in `InitListExpr`.
5374       });
5375 }
5376 
5377 // Repro for a crash that used to occur with chained short-circuiting logical
5378 // operators.
5379 TEST(TransferTest, ChainedLogicalOps) {
5380   std::string Code = R"(
5381     bool target() {
5382       bool b = true || false || false || false;
5383       // [[p]]
5384       return b;
5385     }
5386   )";
5387   runDataflow(
5388       Code,
5389       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5390          ASTContext &ASTCtx) {
5391         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5392         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
5393         EXPECT_TRUE(Env.flowConditionImplies(B));
5394       });
5395 }
5396 
5397 // Repro for a crash that used to occur when we call a `noreturn` function
5398 // within one of the operands of a `&&` or `||` operator.
5399 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5400   std::string Code = R"(
5401     __attribute__((noreturn)) int doesnt_return();
5402     bool some_condition();
5403     void target(bool b1, bool b2) {
5404       // Neither of these should crash. In addition, if we don't terminate the
5405       // program, we know that the operators need to trigger the short-circuit
5406       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5407       // will be true.
5408       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5409       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5410 
5411       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5412       // entire expression unreachable. So we know that in both of the following
5413       // cases, if `target()` terminates, the `else` branch was taken.
5414       bool NoreturnOnLhsMakesAndUnreachable = false;
5415       if (some_condition())
5416          doesnt_return() > 0 && some_condition();
5417       else
5418          NoreturnOnLhsMakesAndUnreachable = true;
5419 
5420       bool NoreturnOnLhsMakesOrUnreachable = false;
5421       if (some_condition())
5422          doesnt_return() > 0 || some_condition();
5423       else
5424          NoreturnOnLhsMakesOrUnreachable = true;
5425 
5426       // [[p]]
5427     }
5428   )";
5429   runDataflow(
5430       Code,
5431       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5432          ASTContext &ASTCtx) {
5433         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5434         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5435         auto &A = Env.arena();
5436 
5437         // Check that [[p]] is reachable with a non-false flow condition.
5438         EXPECT_FALSE(Env.flowConditionImplies(A.makeLiteral(false)));
5439 
5440         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
5441         EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(B1)));
5442 
5443         auto &NoreturnOnRhsOfAnd =
5444             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
5445         EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(NoreturnOnRhsOfAnd)));
5446 
5447         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
5448         EXPECT_TRUE(Env.flowConditionImplies(B2));
5449 
5450         auto &NoreturnOnRhsOfOr =
5451             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
5452                 .formula();
5453         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr));
5454 
5455         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5456             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
5457         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable));
5458 
5459         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5460             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
5461         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable));
5462       });
5463 }
5464 
5465 TEST(TransferTest, NewExpressions) {
5466   std::string Code = R"(
5467     void target() {
5468       int *p = new int(42);
5469       // [[after_new]]
5470     }
5471   )";
5472   runDataflow(
5473       Code,
5474       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5475          ASTContext &ASTCtx) {
5476         const Environment &Env =
5477             getEnvironmentAtAnnotation(Results, "after_new");
5478 
5479         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5480 
5481         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5482       });
5483 }
5484 
5485 TEST(TransferTest, NewExpressions_Structs) {
5486   std::string Code = R"(
5487     struct Inner {
5488       int InnerField;
5489     };
5490 
5491     struct Outer {
5492       Inner OuterField;
5493     };
5494 
5495     void target() {
5496       Outer *p = new Outer;
5497       // Access the fields to make sure the analysis actually generates children
5498       // for them in the `RecordStorageLocation` and `RecordValue`.
5499       p->OuterField.InnerField;
5500       // [[after_new]]
5501     }
5502   )";
5503   runDataflow(
5504       Code,
5505       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5506          ASTContext &ASTCtx) {
5507         const Environment &Env =
5508             getEnvironmentAtAnnotation(Results, "after_new");
5509 
5510         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5511         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5512 
5513         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5514 
5515         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
5516         auto &OuterFieldLoc =
5517             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
5518         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
5519 
5520         // Values for the struct and all fields exist after the new.
5521         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5522         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5523         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5524       });
5525 }
5526 
5527 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5528   std::string Code = R"(
5529     struct A { static void static_member_func(); };
5530     void target() {
5531       // To check that we're treating function-to-pointer decay correctly,
5532       // create two pointers, then verify they refer to the same storage
5533       // location.
5534       // We need to do the test this way because even if an initializer (in this
5535       // case, the function-to-pointer decay) does not create a value, we still
5536       // create a value for the variable.
5537       void (*non_member_p1)() = target;
5538       void (*non_member_p2)() = target;
5539 
5540       // Do the same thing but for a static member function.
5541       void (*member_p1)() = A::static_member_func;
5542       void (*member_p2)() = A::static_member_func;
5543       // [[p]]
5544     }
5545   )";
5546   runDataflow(
5547       Code,
5548       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5549          ASTContext &ASTCtx) {
5550         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5551 
5552         auto &NonMemberP1 =
5553             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
5554         auto &NonMemberP2 =
5555             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
5556         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
5557 
5558         auto &MemberP1 =
5559             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
5560         auto &MemberP2 =
5561             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
5562         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
5563       });
5564 }
5565 
5566 // Check that a builtin function is not associated with a value. (It's only
5567 // possible to call builtin functions directly, not take their address.)
5568 TEST(TransferTest, BuiltinFunctionModeled) {
5569   std::string Code = R"(
5570     void target() {
5571       __builtin_expect(0, 0);
5572       // [[p]]
5573     }
5574   )";
5575   runDataflow(
5576       Code,
5577       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5578          ASTContext &ASTCtx) {
5579         using ast_matchers::selectFirst;
5580         using ast_matchers::match;
5581         using ast_matchers::traverse;
5582         using ast_matchers::implicitCastExpr;
5583         using ast_matchers::hasCastKind;
5584 
5585         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5586 
5587         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
5588             "implicit_cast",
5589             match(traverse(TK_AsIs,
5590                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
5591                                .bind("implicit_cast")),
5592                   ASTCtx));
5593 
5594         ASSERT_THAT(ImplicitCast, NotNull());
5595         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
5596       });
5597 }
5598 
5599 // Check that a callee of a member operator call is modeled as a `PointerValue`.
5600 // Member operator calls are unusual in that their callee is a pointer that
5601 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
5602 // member functions, the callee is a `MemberExpr` (which does not have pointer
5603 // type).
5604 // We want to make sure that we produce a pointer value for the callee in this
5605 // specific scenario and that its storage location is durable (for convergence).
5606 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
5607   std::string Code = R"(
5608     struct S {
5609       bool operator!=(S s);
5610     };
5611     void target() {
5612       S s;
5613       (void)(s != s);
5614       (void)(s != s);
5615       // [[p]]
5616     }
5617   )";
5618   runDataflow(
5619       Code,
5620       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5621          ASTContext &ASTCtx) {
5622         using ast_matchers::selectFirst;
5623         using ast_matchers::match;
5624         using ast_matchers::traverse;
5625         using ast_matchers::cxxOperatorCallExpr;
5626 
5627         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5628 
5629         auto Matches = match(
5630             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
5631 
5632         ASSERT_EQ(Matches.size(), 2UL);
5633 
5634         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
5635         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
5636 
5637         ASSERT_THAT(Call1, NotNull());
5638         ASSERT_THAT(Call2, NotNull());
5639 
5640         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
5641                   CK_FunctionToPointerDecay);
5642         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
5643                   CK_FunctionToPointerDecay);
5644 
5645         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
5646         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
5647 
5648         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
5649       });
5650 }
5651 
5652 // Check that fields of anonymous records are modeled.
5653 TEST(TransferTest, AnonymousStruct) {
5654   std::string Code = R"(
5655     struct S {
5656       struct {
5657         bool b;
5658       };
5659     };
5660     void target() {
5661       S s;
5662       s.b = true;
5663       // [[p]]
5664     }
5665   )";
5666   runDataflow(
5667       Code,
5668       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5669          ASTContext &ASTCtx) {
5670         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5671         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5672         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5673         const IndirectFieldDecl *IndirectField =
5674             findIndirectFieldDecl(ASTCtx, "b");
5675 
5676         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
5677         auto &AnonStruct = *cast<RecordStorageLocation>(
5678             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
5679 
5680         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5681         ASSERT_TRUE(Env.flowConditionImplies(B->formula()));
5682       });
5683 }
5684 
5685 TEST(TransferTest, AnonymousStructWithInitializer) {
5686   std::string Code = R"(
5687     struct target {
5688       target() {
5689         (void)0;
5690         // [[p]]
5691       }
5692       struct {
5693         bool b = true;
5694       };
5695     };
5696   )";
5697   runDataflow(
5698       Code,
5699       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5700          ASTContext &ASTCtx) {
5701         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5702         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5703         const IndirectFieldDecl *IndirectField =
5704             findIndirectFieldDecl(ASTCtx, "b");
5705 
5706         auto *ThisLoc =
5707             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
5708         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
5709             *cast<ValueDecl>(IndirectField->chain().front())));
5710 
5711         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5712         ASSERT_TRUE(Env.flowConditionImplies(B->formula()));
5713       });
5714 }
5715 
5716 TEST(TransferTest, AnonymousStructWithReferenceField) {
5717   std::string Code = R"(
5718     int global_i = 0;
5719     struct target {
5720       target() {
5721         (void)0;
5722         // [[p]]
5723       }
5724       struct {
5725         int &i = global_i;
5726       };
5727     };
5728   )";
5729   runDataflow(
5730       Code,
5731       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5732          ASTContext &ASTCtx) {
5733         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5734         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
5735         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
5736         const IndirectFieldDecl *IndirectField =
5737             findIndirectFieldDecl(ASTCtx, "i");
5738 
5739         auto *ThisLoc =
5740             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
5741         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
5742             *cast<ValueDecl>(IndirectField->chain().front())));
5743 
5744         ASSERT_EQ(AnonStruct.getChild(*IDecl),
5745                   Env.getStorageLocation(*GlobalIDecl));
5746       });
5747 }
5748 
5749 } // namespace
5750