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