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