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