xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision ca7d9442baf638f020c9594dc2af388d24c4a3e1)
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         // The field of the base class should already have been initialized with
1586         // a value by the base constructor.
1587         EXPECT_NE(getFieldValue(Env.getThisPointeeStorageLocation(), "BaseVal",
1588                                 ASTCtx, Env),
1589                   nullptr);
1590         EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "Val",
1591                                 ASTCtx, Env),
1592                   nullptr);
1593       });
1594 }
1595 
1596 TEST(TransferTest, StructModeledFieldsWithAccessor) {
1597   std::string Code = R"(
1598     class S {
1599       int *Ptr;
1600       int *PtrNonConst;
1601       int Int;
1602       int IntWithInc;
1603       int IntNotAccessed;
1604       int IntRef;
1605     public:
1606       int *getPtr() const { return Ptr; }
1607       int *getPtrNonConst() { return PtrNonConst; }
1608       int getInt(int i) const { return Int; }
1609       int getWithInc(int i) { IntWithInc += i; return IntWithInc; }
1610       int getIntNotAccessed() const { return IntNotAccessed; }
1611       int getIntNoDefinition() const;
1612       int &getIntRef() { return IntRef; }
1613       void returnVoid() const { return; }
1614     };
1615 
1616     void target() {
1617       S s;
1618       int *p1 = s.getPtr();
1619       int *p2 = s.getPtrNonConst();
1620       int i1 = s.getInt(1);
1621       int i2 = s.getWithInc(1);
1622       int i3 = s.getIntNoDefinition();
1623       int &iref = s.getIntRef();
1624 
1625       // Regression test: Don't crash on an indirect call (which doesn't have
1626       // an associated `CXXMethodDecl`).
1627       auto ptr_to_member_fn = &S::getPtr;
1628       p1 = (s.*ptr_to_member_fn)();
1629 
1630       // Regression test: Don't crash on a return statement without a value.
1631       s.returnVoid();
1632       // [[p]]
1633     }
1634   )";
1635   runDataflow(
1636       Code,
1637       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1638          ASTContext &ASTCtx) {
1639         const Environment &Env =
1640               getEnvironmentAtAnnotation(Results, "p");
1641         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
1642         std::vector<const ValueDecl*> Fields;
1643         for (auto [Field, _] : SLoc.children())
1644           Fields.push_back(Field);
1645         // Only the fields that have simple accessor methods (that have a
1646         // single statement body that returns the member variable) should be
1647         // modeled.
1648         ASSERT_THAT(Fields, UnorderedElementsAre(
1649             findValueDecl(ASTCtx, "Ptr"), findValueDecl(ASTCtx, "PtrNonConst"),
1650             findValueDecl(ASTCtx, "Int"), findValueDecl(ASTCtx, "IntRef")));
1651       });
1652 }
1653 
1654 TEST(TransferTest, StructModeledFieldsWithComplicatedInheritance) {
1655   std::string Code = R"(
1656     struct Base1 {
1657       int base1_1;
1658       int base1_2;
1659     };
1660     struct Intermediate : Base1 {
1661       int intermediate_1;
1662       int intermediate_2;
1663     };
1664     struct Base2 {
1665       int base2_1;
1666       int base2_2;
1667     };
1668     struct MostDerived : public Intermediate, Base2 {
1669       int most_derived_1;
1670       int most_derived_2;
1671     };
1672 
1673     void target() {
1674       MostDerived MD;
1675       MD.base1_2 = 1;
1676       MD.intermediate_2 = 1;
1677       MD.base2_2 = 1;
1678       MD.most_derived_2 = 1;
1679       // [[p]]
1680     }
1681   )";
1682   runDataflow(
1683       Code,
1684       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1685          ASTContext &ASTCtx) {
1686         const Environment &Env =
1687               getEnvironmentAtAnnotation(Results, "p");
1688 
1689         // Only the accessed fields should exist in the model.
1690         auto &MDLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1691         std::vector<const ValueDecl*> Fields;
1692         for (auto [Field, _] : MDLoc.children())
1693           Fields.push_back(Field);
1694         ASSERT_THAT(Fields, UnorderedElementsAre(
1695             findValueDecl(ASTCtx, "base1_2"),
1696             findValueDecl(ASTCtx, "intermediate_2"),
1697             findValueDecl(ASTCtx, "base2_2"),
1698             findValueDecl(ASTCtx, "most_derived_2")));
1699       });
1700 }
1701 
1702 TEST(TransferTest, StructInitializerListWithComplicatedInheritance) {
1703   std::string Code = R"(
1704     struct Base1 {
1705       int base1;
1706     };
1707     struct Intermediate : Base1 {
1708       int intermediate;
1709     };
1710     struct Base2 {
1711       int base2;
1712     };
1713     struct MostDerived : public Intermediate, Base2 {
1714       int most_derived;
1715     };
1716 
1717     void target() {
1718       MostDerived MD = {};
1719       // [[p]]
1720     }
1721   )";
1722   runDataflow(
1723       Code,
1724       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1725          ASTContext &ASTCtx) {
1726         const Environment &Env =
1727               getEnvironmentAtAnnotation(Results, "p");
1728 
1729         // When a struct is initialized with a initializer list, all the
1730         // fields are considered "accessed", and therefore do exist.
1731         auto &MD = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1732         ASSERT_THAT(cast<IntegerValue>(
1733             getFieldValue(&MD, *findValueDecl(ASTCtx, "base1"), Env)),
1734             NotNull());
1735         ASSERT_THAT(cast<IntegerValue>(
1736             getFieldValue(&MD, *findValueDecl(ASTCtx, "intermediate"), Env)),
1737             NotNull());
1738         ASSERT_THAT(cast<IntegerValue>(
1739             getFieldValue(&MD, *findValueDecl(ASTCtx, "base2"), Env)),
1740             NotNull());
1741         ASSERT_THAT(cast<IntegerValue>(
1742             getFieldValue(&MD, *findValueDecl(ASTCtx, "most_derived"), Env)),
1743             NotNull());
1744       });
1745 }
1746 
1747 TEST(TransferTest, ReferenceMember) {
1748   std::string Code = R"(
1749     struct A {
1750       int &Bar;
1751     };
1752 
1753     void target(A Foo) {
1754       int Baz = Foo.Bar;
1755       // [[p]]
1756     }
1757   )";
1758   runDataflow(
1759       Code,
1760       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1761          ASTContext &ASTCtx) {
1762         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1763         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1764 
1765         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1766         ASSERT_THAT(FooDecl, NotNull());
1767 
1768         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1769         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1770 
1771         FieldDecl *BarDecl = nullptr;
1772         for (FieldDecl *Field : FooFields) {
1773           if (Field->getNameAsString() == "Bar") {
1774             BarDecl = Field;
1775           } else {
1776             FAIL() << "Unexpected field: " << Field->getNameAsString();
1777           }
1778         }
1779         ASSERT_THAT(BarDecl, NotNull());
1780 
1781         const auto *FooLoc =
1782             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1783         const auto *BarReferentVal =
1784             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1785 
1786         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1787         ASSERT_THAT(BazDecl, NotNull());
1788 
1789         EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal);
1790       });
1791 }
1792 
1793 TEST(TransferTest, StructThisMember) {
1794   std::string Code = R"(
1795     struct A {
1796       int Bar;
1797 
1798       struct B {
1799         int Baz;
1800       };
1801 
1802       B Qux;
1803 
1804       void target() {
1805         int Foo = Bar;
1806         int Quux = Qux.Baz;
1807         // [[p]]
1808       }
1809     };
1810   )";
1811   runDataflow(
1812       Code,
1813       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1814          ASTContext &ASTCtx) {
1815         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1816         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1817 
1818         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1819         ASSERT_THAT(ThisLoc, NotNull());
1820 
1821         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1822         ASSERT_THAT(BarDecl, NotNull());
1823 
1824         const auto *BarLoc =
1825             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1826         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1827 
1828         const Value *BarVal = Env.getValue(*BarLoc);
1829         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1830 
1831         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1832         ASSERT_THAT(FooDecl, NotNull());
1833         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1834 
1835         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1836         ASSERT_THAT(QuxDecl, NotNull());
1837 
1838         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1839         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1840 
1841         FieldDecl *BazDecl = nullptr;
1842         for (FieldDecl *Field : QuxFields) {
1843           if (Field->getNameAsString() == "Baz") {
1844             BazDecl = Field;
1845           } else {
1846             FAIL() << "Unexpected field: " << Field->getNameAsString();
1847           }
1848         }
1849         ASSERT_THAT(BazDecl, NotNull());
1850 
1851         const auto *QuxLoc =
1852             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1853         EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
1854 
1855         const auto *BazVal =
1856             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1857 
1858         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1859         ASSERT_THAT(QuuxDecl, NotNull());
1860         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1861       });
1862 }
1863 
1864 TEST(TransferTest, ClassThisMember) {
1865   std::string Code = R"(
1866     class A {
1867       int Bar;
1868 
1869       class B {
1870       public:
1871         int Baz;
1872       };
1873 
1874       B Qux;
1875 
1876       void target() {
1877         int Foo = Bar;
1878         int Quux = Qux.Baz;
1879         // [[p]]
1880       }
1881     };
1882   )";
1883   runDataflow(
1884       Code,
1885       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1886          ASTContext &ASTCtx) {
1887         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1888         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1889 
1890         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1891 
1892         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1893         ASSERT_THAT(BarDecl, NotNull());
1894 
1895         const auto *BarLoc =
1896             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1897         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1898 
1899         const Value *BarVal = Env.getValue(*BarLoc);
1900         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1901 
1902         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1903         ASSERT_THAT(FooDecl, NotNull());
1904         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1905 
1906         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1907         ASSERT_THAT(QuxDecl, NotNull());
1908 
1909         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1910         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1911 
1912         FieldDecl *BazDecl = nullptr;
1913         for (FieldDecl *Field : QuxFields) {
1914           if (Field->getNameAsString() == "Baz") {
1915             BazDecl = Field;
1916           } else {
1917             FAIL() << "Unexpected field: " << Field->getNameAsString();
1918           }
1919         }
1920         ASSERT_THAT(BazDecl, NotNull());
1921 
1922         const auto *QuxLoc =
1923             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1924         EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
1925 
1926         const auto *BazVal =
1927             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1928 
1929         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1930         ASSERT_THAT(QuuxDecl, NotNull());
1931         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1932       });
1933 }
1934 
1935 TEST(TransferTest, UnionThisMember) {
1936   std::string Code = R"(
1937     union A {
1938       int Foo;
1939       int Bar;
1940 
1941       void target() {
1942         A a;
1943         // Mention the fields to ensure they're included in the analysis.
1944         (void)a.Foo;
1945         (void)a.Bar;
1946         // [[p]]
1947       }
1948     };
1949   )";
1950   runDataflow(
1951       Code,
1952       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1953          ASTContext &ASTCtx) {
1954         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1955         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1956 
1957         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1958         ASSERT_THAT(ThisLoc, NotNull());
1959 
1960         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1961         ASSERT_THAT(FooDecl, NotNull());
1962 
1963         const auto *FooLoc =
1964             cast<ScalarStorageLocation>(ThisLoc->getChild(*FooDecl));
1965         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1966 
1967         const Value *FooVal = Env.getValue(*FooLoc);
1968         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1969 
1970         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1971         ASSERT_THAT(BarDecl, NotNull());
1972 
1973         const auto *BarLoc =
1974             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1975         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1976 
1977         const Value *BarVal = Env.getValue(*BarLoc);
1978         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1979       });
1980 }
1981 
1982 TEST(TransferTest, StructThisInLambda) {
1983   std::string ThisCaptureCode = R"(
1984     struct A {
1985       void frob() {
1986         [this]() {
1987           int Foo = Bar;
1988           // [[p1]]
1989         }();
1990       }
1991 
1992       int Bar;
1993     };
1994   )";
1995   runDataflow(
1996       ThisCaptureCode,
1997       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1998          ASTContext &ASTCtx) {
1999         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
2000         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
2001 
2002         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2003         ASSERT_THAT(ThisLoc, NotNull());
2004 
2005         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2006         ASSERT_THAT(BarDecl, NotNull());
2007 
2008         const auto *BarLoc =
2009             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
2010         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2011 
2012         const Value *BarVal = Env.getValue(*BarLoc);
2013         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2014 
2015         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2016         ASSERT_THAT(FooDecl, NotNull());
2017         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
2018       },
2019       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2020 
2021   std::string RefCaptureDefaultCode = R"(
2022     struct A {
2023       void frob() {
2024         [&]() {
2025           int Foo = Bar;
2026           // [[p2]]
2027         }();
2028       }
2029 
2030       int Bar;
2031     };
2032   )";
2033   runDataflow(
2034       RefCaptureDefaultCode,
2035       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2036          ASTContext &ASTCtx) {
2037         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
2038         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
2039 
2040         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2041         ASSERT_THAT(ThisLoc, NotNull());
2042 
2043         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2044         ASSERT_THAT(BarDecl, NotNull());
2045 
2046         const auto *BarLoc =
2047             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
2048         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2049 
2050         const Value *BarVal = Env.getValue(*BarLoc);
2051         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2052 
2053         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2054         ASSERT_THAT(FooDecl, NotNull());
2055         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
2056       },
2057       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2058 
2059   std::string FreeFunctionLambdaCode = R"(
2060     void foo() {
2061       int Bar;
2062       [&]() {
2063         int Foo = Bar;
2064         // [[p3]]
2065       }();
2066     }
2067   )";
2068   runDataflow(
2069       FreeFunctionLambdaCode,
2070       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2071          ASTContext &ASTCtx) {
2072         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
2073         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
2074 
2075         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
2076       },
2077       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2078 }
2079 
2080 TEST(TransferTest, ConstructorInitializer) {
2081   std::string Code = R"(
2082     struct target {
2083       int Bar;
2084 
2085       target(int Foo) : Bar(Foo) {
2086         int Qux = Bar;
2087         // [[p]]
2088       }
2089     };
2090   )";
2091   runDataflow(
2092       Code,
2093       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2094          ASTContext &ASTCtx) {
2095         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2096         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2097 
2098         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2099         ASSERT_THAT(ThisLoc, NotNull());
2100 
2101         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2102         ASSERT_THAT(FooDecl, NotNull());
2103 
2104         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
2105 
2106         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2107         ASSERT_THAT(QuxDecl, NotNull());
2108         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
2109       });
2110 }
2111 
2112 TEST(TransferTest, DefaultInitializer) {
2113   std::string Code = R"(
2114     struct target {
2115       int Bar;
2116       int Baz = Bar;
2117 
2118       target(int Foo) : Bar(Foo) {
2119         int Qux = Baz;
2120         // [[p]]
2121       }
2122     };
2123   )";
2124   runDataflow(
2125       Code,
2126       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2127          ASTContext &ASTCtx) {
2128         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2129         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2130 
2131         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2132         ASSERT_THAT(ThisLoc, NotNull());
2133 
2134         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2135         ASSERT_THAT(FooDecl, NotNull());
2136 
2137         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
2138 
2139         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2140         ASSERT_THAT(QuxDecl, NotNull());
2141         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
2142       });
2143 }
2144 
2145 TEST(TransferTest, DefaultInitializerReference) {
2146   std::string Code = R"(
2147     struct target {
2148       int &Bar;
2149       int &Baz = Bar;
2150 
2151       target(int &Foo) : Bar(Foo) {
2152         int &Qux = Baz;
2153         // [[p]]
2154       }
2155     };
2156   )";
2157   runDataflow(
2158       Code,
2159       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2160          ASTContext &ASTCtx) {
2161         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2162         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2163 
2164         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2165         ASSERT_THAT(ThisLoc, NotNull());
2166 
2167         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2168         ASSERT_THAT(FooDecl, NotNull());
2169 
2170         const auto *FooLoc = Env.getStorageLocation(*FooDecl);
2171 
2172         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2173         ASSERT_THAT(QuxDecl, NotNull());
2174 
2175         const auto *QuxLoc = Env.getStorageLocation(*QuxDecl);
2176         EXPECT_EQ(QuxLoc, FooLoc);
2177       });
2178 }
2179 
2180 TEST(TransferTest, TemporaryObject) {
2181   std::string Code = R"(
2182     struct A {
2183       int Bar;
2184     };
2185 
2186     void target() {
2187       A Foo = A();
2188       (void)Foo.Bar;
2189       // [[p]]
2190     }
2191   )";
2192   runDataflow(
2193       Code,
2194       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2195          ASTContext &ASTCtx) {
2196         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2197         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2198 
2199         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2200         ASSERT_THAT(FooDecl, NotNull());
2201 
2202         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2203         ASSERT_THAT(BarDecl, NotNull());
2204 
2205         const auto *FooLoc =
2206             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2207         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2208       });
2209 }
2210 
2211 TEST(TransferTest, ElidableConstructor) {
2212   // This test is effectively the same as TransferTest.TemporaryObject, but
2213   // the code is compiled as C++14.
2214   std::string Code = R"(
2215     struct A {
2216       int Bar;
2217     };
2218 
2219     void target() {
2220       A Foo = A();
2221       (void)Foo.Bar;
2222       // [[p]]
2223     }
2224   )";
2225   runDataflow(
2226       Code,
2227       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2228          ASTContext &ASTCtx) {
2229         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2230         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2231 
2232         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2233         ASSERT_THAT(FooDecl, NotNull());
2234 
2235         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2236         ASSERT_THAT(BarDecl, NotNull());
2237 
2238         const auto *FooLoc =
2239             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2240         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2241       },
2242       LangStandard::lang_cxx14);
2243 }
2244 
2245 TEST(TransferTest, AssignmentOperator) {
2246   std::string Code = R"(
2247     struct A {
2248       int Baz;
2249     };
2250 
2251     void target() {
2252       A Foo = { 1 };
2253       A Bar = { 2 };
2254       // [[p1]]
2255       Foo = Bar;
2256       // [[p2]]
2257       Foo.Baz = 3;
2258       // [[p3]]
2259     }
2260   )";
2261   runDataflow(
2262       Code,
2263       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2264          ASTContext &ASTCtx) {
2265         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2266         ASSERT_THAT(FooDecl, NotNull());
2267 
2268         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2269         ASSERT_THAT(BarDecl, NotNull());
2270 
2271         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2272         ASSERT_THAT(BazDecl, NotNull());
2273 
2274         // Before copy assignment.
2275         {
2276           const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2277 
2278           const auto *FooLoc1 =
2279               cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2280           const auto *BarLoc1 =
2281               cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2282           EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2283 
2284           const auto *FooBazVal1 =
2285               cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2286           const auto *BarBazVal1 =
2287               cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2288           EXPECT_NE(FooBazVal1, BarBazVal1);
2289         }
2290 
2291         // After copy assignment.
2292         {
2293           const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2294 
2295           const auto *FooLoc2 =
2296               cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2297           const auto *BarLoc2 =
2298               cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl));
2299 
2300           const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
2301           const auto *BarVal2 = cast<RecordValue>(Env2.getValue(*BarLoc2));
2302           EXPECT_NE(FooVal2, BarVal2);
2303 
2304           EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2));
2305 
2306           const auto *FooBazVal2 =
2307               cast<IntegerValue>(getFieldValue(FooLoc2, *BazDecl, Env2));
2308           const auto *BarBazVal2 =
2309               cast<IntegerValue>(getFieldValue(BarLoc2, *BazDecl, Env2));
2310           EXPECT_EQ(FooBazVal2, BarBazVal2);
2311         }
2312 
2313         // After value update.
2314         {
2315           const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
2316 
2317           const auto *FooLoc3 =
2318               cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl));
2319           const auto *BarLoc3 =
2320               cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl));
2321           EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3));
2322 
2323           const auto *FooBazVal3 =
2324               cast<IntegerValue>(getFieldValue(FooLoc3, *BazDecl, Env3));
2325           const auto *BarBazVal3 =
2326               cast<IntegerValue>(getFieldValue(BarLoc3, *BazDecl, Env3));
2327           EXPECT_NE(FooBazVal3, BarBazVal3);
2328         }
2329       });
2330 }
2331 
2332 // It's legal for the assignment operator to take its source parameter by value.
2333 // Check that we handle this correctly. (This is a repro -- we used to
2334 // assert-fail on this.)
2335 TEST(TransferTest, AssignmentOperator_ArgByValue) {
2336   std::string Code = R"(
2337     struct A {
2338       int Baz;
2339       A &operator=(A);
2340     };
2341 
2342     void target() {
2343       A Foo = { 1 };
2344       A Bar = { 2 };
2345       Foo = Bar;
2346       // [[p]]
2347     }
2348   )";
2349   runDataflow(
2350       Code,
2351       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2352          ASTContext &ASTCtx) {
2353         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2354         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2355 
2356         const auto &FooLoc =
2357             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2358         const auto &BarLoc =
2359             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2360 
2361         const auto *FooBazVal =
2362             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2363         const auto *BarBazVal =
2364             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2365         EXPECT_EQ(FooBazVal, BarBazVal);
2366       });
2367 }
2368 
2369 TEST(TransferTest, AssignmentOperatorFromBase) {
2370   std::string Code = R"(
2371     struct Base {
2372       int base;
2373     };
2374     struct Derived : public Base {
2375       using Base::operator=;
2376       int derived;
2377     };
2378     void target(Base B, Derived D) {
2379       D.base = 1;
2380       D.derived = 1;
2381       // [[before]]
2382       D = B;
2383       // [[after]]
2384     }
2385   )";
2386   runDataflow(
2387       Code,
2388       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2389          ASTContext &ASTCtx) {
2390         const Environment &EnvBefore =
2391             getEnvironmentAtAnnotation(Results, "before");
2392         const Environment &EnvAfter =
2393             getEnvironmentAtAnnotation(Results, "after");
2394 
2395         auto &BLoc =
2396             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "B");
2397         auto &DLoc =
2398             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "D");
2399 
2400         EXPECT_NE(getFieldValue(&BLoc, "base", ASTCtx, EnvBefore),
2401                   getFieldValue(&DLoc, "base", ASTCtx, EnvBefore));
2402         EXPECT_EQ(getFieldValue(&BLoc, "base", ASTCtx, EnvAfter),
2403                   getFieldValue(&DLoc, "base", ASTCtx, EnvAfter));
2404 
2405         EXPECT_EQ(getFieldValue(&DLoc, "derived", ASTCtx, EnvBefore),
2406                   getFieldValue(&DLoc, "derived", ASTCtx, EnvAfter));
2407       });
2408 }
2409 
2410 TEST(TransferTest, AssignmentOperatorFromCallResult) {
2411   std::string Code = R"(
2412     struct A {};
2413     A ReturnA();
2414 
2415     void target() {
2416       A MyA;
2417       MyA = ReturnA();
2418     }
2419   )";
2420   runDataflow(
2421       Code,
2422       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2423          ASTContext &ASTCtx) {
2424         // As of this writing, we don't produce a `Value` for the call
2425         // `ReturnA()`. The only condition we're testing for is that the
2426         // analysis should not crash in this case.
2427       });
2428 }
2429 
2430 TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) {
2431   // This is a crash repro.
2432   std::string Code = R"(
2433     struct B { int Foo; };
2434     struct S : public B {};
2435     void target() {
2436       S S1 = { 1 };
2437       S S2;
2438       S S3;
2439       S1 = S2;  // Only Dst has InitListExpr.
2440       S3 = S1;  // Only Src has InitListExpr.
2441       // [[p]]
2442     }
2443   )";
2444   runDataflow(
2445       Code,
2446       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2447          ASTContext &ASTCtx) {});
2448 }
2449 
2450 TEST(TransferTest, AssignmentOperatorReturnsVoid) {
2451   // This is a crash repro.
2452   std::string Code = R"(
2453     struct S {
2454       void operator=(S&& other);
2455     };
2456     void target() {
2457       S s;
2458       s = S();
2459       // [[p]]
2460     }
2461   )";
2462   runDataflow(
2463       Code,
2464       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2465          ASTContext &ASTCtx) {});
2466 }
2467 
2468 TEST(TransferTest, AssignmentOperatorReturnsByValue) {
2469   // This is a crash repro.
2470   std::string Code = R"(
2471     struct S {
2472       S operator=(S&& other);
2473     };
2474     void target() {
2475       S s;
2476       s = S();
2477       // [[p]]
2478     }
2479   )";
2480   runDataflow(
2481       Code,
2482       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2483          ASTContext &ASTCtx) {});
2484 }
2485 
2486 TEST(TransferTest, InitListExprAsXValue) {
2487   // This is a crash repro.
2488   std::string Code = R"(
2489     void target() {
2490       bool&& Foo{false};
2491       // [[p]]
2492     }
2493   )";
2494   runDataflow(
2495       Code,
2496       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2497          ASTContext &ASTCtx) {
2498         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2499         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
2500         ASSERT_TRUE(FooVal.formula().isLiteral(false));
2501       });
2502 }
2503 
2504 TEST(TransferTest, ArrayInitListExprOneRecordElement) {
2505   // This is a crash repro.
2506   std::string Code = R"cc(
2507     struct S {};
2508 
2509     void target() { S foo[] = {S()}; }
2510   )cc";
2511   runDataflow(
2512       Code,
2513       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2514          ASTContext &ASTCtx) {
2515         // Just verify that it doesn't crash.
2516       });
2517 }
2518 
2519 TEST(TransferTest, InitListExprAsUnion) {
2520   // This is a crash repro.
2521   std::string Code = R"cc(
2522     class target {
2523       union {
2524         int *a;
2525         bool *b;
2526       } F;
2527 
2528      public:
2529       constexpr target() : F{nullptr} {
2530         int *null = nullptr;
2531         F.b;  // Make sure we reference 'b' so it is modeled.
2532         // [[p]]
2533       }
2534     };
2535   )cc";
2536   runDataflow(
2537       Code,
2538       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2539          ASTContext &ASTCtx) {
2540         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2541 
2542         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2543             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2544         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2545         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2546         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2547       });
2548 }
2549 
2550 TEST(TransferTest, EmptyInitListExprForUnion) {
2551   // This is a crash repro.
2552   std::string Code = R"cc(
2553     class target {
2554       union {
2555         int *a;
2556         bool *b;
2557       } F;
2558 
2559      public:
2560       // Empty initializer list means that `F` is aggregate-initialized.
2561       // For a union, this has the effect that the first member of the union
2562       // is copy-initialized from an empty initializer list; in this specific
2563       // case, this has the effect of initializing `a` with null.
2564       constexpr target() : F{} {
2565         int *null = nullptr;
2566         F.b;  // Make sure we reference 'b' so it is modeled.
2567         // [[p]]
2568       }
2569     };
2570   )cc";
2571   runDataflow(
2572       Code,
2573       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2574          ASTContext &ASTCtx) {
2575         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2576 
2577         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2578             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2579         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2580         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2581         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2582       });
2583 }
2584 
2585 TEST(TransferTest, EmptyInitListExprForStruct) {
2586   std::string Code = R"cc(
2587     class target {
2588       struct {
2589         int *a;
2590         bool *b;
2591       } F;
2592 
2593      public:
2594       constexpr target() : F{} {
2595         int *NullIntPtr = nullptr;
2596         bool *NullBoolPtr = nullptr;
2597         // [[p]]
2598       }
2599     };
2600   )cc";
2601   runDataflow(
2602       Code,
2603       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2604          ASTContext &ASTCtx) {
2605         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2606 
2607         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2608             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2609         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2610         EXPECT_EQ(AVal,
2611                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullIntPtr"));
2612         auto *BVal = cast<PointerValue>(getFieldValue(&FLoc, "b", ASTCtx, Env));
2613         EXPECT_EQ(BVal,
2614                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullBoolPtr"));
2615       });
2616 }
2617 
2618 TEST(TransferTest, CopyConstructor) {
2619   std::string Code = R"(
2620     struct A {
2621       int Baz;
2622     };
2623 
2624     void target() {
2625       A Foo = { 1 };
2626       A Bar = Foo;
2627       // [[after_copy]]
2628       Foo.Baz = 2;
2629       // [[after_update]]
2630     }
2631   )";
2632   runDataflow(
2633       Code,
2634       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2635          ASTContext &ASTCtx) {
2636         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2637         ASSERT_THAT(FooDecl, NotNull());
2638 
2639         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2640         ASSERT_THAT(BarDecl, NotNull());
2641 
2642         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2643         ASSERT_THAT(BazDecl, NotNull());
2644 
2645         // after_copy
2646         {
2647           const Environment &Env =
2648               getEnvironmentAtAnnotation(Results, "after_copy");
2649 
2650           const auto *FooLoc =
2651               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2652           const auto *BarLoc =
2653               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2654 
2655           // `Foo` and `Bar` have different `RecordValue`s associated with them.
2656           const auto *FooVal = cast<RecordValue>(Env.getValue(*FooLoc));
2657           const auto *BarVal = cast<RecordValue>(Env.getValue(*BarLoc));
2658           EXPECT_NE(FooVal, BarVal);
2659 
2660           // But the records compare equal.
2661           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2662 
2663           // In particular, the value of `Baz` in both records is the same.
2664           const auto *FooBazVal =
2665               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2666           const auto *BarBazVal =
2667               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2668           EXPECT_EQ(FooBazVal, BarBazVal);
2669         }
2670 
2671         // after_update
2672         {
2673           const Environment &Env =
2674               getEnvironmentAtAnnotation(Results, "after_update");
2675 
2676           const auto *FooLoc =
2677               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2678           const auto *BarLoc =
2679               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2680 
2681           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2682 
2683           const auto *FooBazVal =
2684               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2685           const auto *BarBazVal =
2686               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2687           EXPECT_NE(FooBazVal, BarBazVal);
2688         }
2689       });
2690 }
2691 
2692 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2693   std::string Code = R"(
2694     struct A {
2695       int Baz;
2696       A() = default;
2697       A(const A& a, bool def = true) { Baz = a.Baz; }
2698     };
2699 
2700     void target() {
2701       A Foo;
2702       (void)Foo.Baz;
2703       A Bar = Foo;
2704       // [[p]]
2705     }
2706   )";
2707   runDataflow(
2708       Code,
2709       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2710          ASTContext &ASTCtx) {
2711         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2712         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2713 
2714         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2715         ASSERT_THAT(FooDecl, NotNull());
2716 
2717         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2718         ASSERT_THAT(BarDecl, NotNull());
2719 
2720         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2721         ASSERT_THAT(BazDecl, NotNull());
2722 
2723         const auto *FooLoc =
2724             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2725         const auto *BarLoc =
2726             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2727         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2728 
2729         const auto *FooBazVal =
2730             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2731         const auto *BarBazVal =
2732             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2733         EXPECT_EQ(FooBazVal, BarBazVal);
2734       });
2735 }
2736 
2737 TEST(TransferTest, CopyConstructorWithParens) {
2738   std::string Code = R"(
2739     struct A {
2740       int Baz;
2741     };
2742 
2743     void target() {
2744       A Foo;
2745       (void)Foo.Baz;
2746       A Bar((A(Foo)));
2747       // [[p]]
2748     }
2749   )";
2750   runDataflow(
2751       Code,
2752       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2753          ASTContext &ASTCtx) {
2754         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2755         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2756 
2757         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2758         ASSERT_THAT(FooDecl, NotNull());
2759 
2760         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2761         ASSERT_THAT(BarDecl, NotNull());
2762 
2763         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2764         ASSERT_THAT(BazDecl, NotNull());
2765 
2766         const auto *FooLoc =
2767             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2768         const auto *BarLoc =
2769             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2770         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2771 
2772         const auto *FooBazVal =
2773             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2774         const auto *BarBazVal =
2775             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2776         EXPECT_EQ(FooBazVal, BarBazVal);
2777       });
2778 }
2779 
2780 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {
2781   std::string Code = R"(
2782   struct A {
2783     int Baz;
2784   };
2785   void target() {
2786     A Foo = {3};
2787     (void)Foo.Baz;
2788     A Bar = {A(Foo)};
2789     // [[p]]
2790   }
2791   )";
2792   runDataflow(
2793       Code,
2794       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2795          ASTContext &ASTCtx) {
2796         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2797 
2798         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2799 
2800         const auto &FooLoc =
2801             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2802         const auto &BarLoc =
2803             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2804 
2805         const auto *FooBazVal =
2806             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2807         const auto *BarBazVal =
2808             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2809         EXPECT_EQ(FooBazVal, BarBazVal);
2810       });
2811 }
2812 
2813 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2814   // This is a crash repro.
2815   std::string Code = R"(
2816     struct S {};
2817     const S &returnsSRef();
2818     void target() {
2819       S s(returnsSRef());
2820     }
2821   )";
2822   runDataflow(
2823       Code,
2824       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2825          ASTContext &ASTCtx) {});
2826 }
2827 
2828 TEST(TransferTest, MoveConstructor) {
2829   std::string Code = R"(
2830     namespace std {
2831 
2832     template <typename T> struct remove_reference      { using type = T; };
2833     template <typename T> struct remove_reference<T&>  { using type = T; };
2834     template <typename T> struct remove_reference<T&&> { using type = T; };
2835 
2836     template <typename T>
2837     using remove_reference_t = typename remove_reference<T>::type;
2838 
2839     template <typename T>
2840     std::remove_reference_t<T>&& move(T&& x);
2841 
2842     } // namespace std
2843 
2844     struct A {
2845       int Baz;
2846     };
2847 
2848     void target() {
2849       A Foo;
2850       A Bar;
2851       (void)Foo.Baz;
2852       // [[p1]]
2853       Foo = std::move(Bar);
2854       // [[p2]]
2855     }
2856   )";
2857   runDataflow(
2858       Code,
2859       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2860          ASTContext &ASTCtx) {
2861         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2862         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2863         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2864 
2865         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2866         ASSERT_THAT(FooDecl, NotNull());
2867 
2868         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2869         ASSERT_THAT(BarDecl, NotNull());
2870 
2871         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2872         ASSERT_THAT(BazDecl, NotNull());
2873 
2874         const auto *FooLoc1 =
2875             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2876         const auto *BarLoc1 =
2877             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2878 
2879         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2880 
2881         const auto *FooVal1 = cast<RecordValue>(Env1.getValue(*FooLoc1));
2882         const auto *BarVal1 = cast<RecordValue>(Env1.getValue(*BarLoc1));
2883         EXPECT_NE(FooVal1, BarVal1);
2884 
2885         const auto *FooBazVal1 =
2886             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2887         const auto *BarBazVal1 =
2888             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2889         EXPECT_NE(FooBazVal1, BarBazVal1);
2890 
2891         const auto *FooLoc2 =
2892             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2893         const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
2894         EXPECT_NE(FooVal2, BarVal1);
2895         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2896 
2897         const auto *FooBazVal2 =
2898             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2899         EXPECT_EQ(FooBazVal2, BarBazVal1);
2900       });
2901 }
2902 
2903 TEST(TransferTest, BindTemporary) {
2904   std::string Code = R"(
2905     struct A {
2906       virtual ~A() = default;
2907 
2908       int Baz;
2909     };
2910 
2911     void target(A Foo) {
2912       int Bar = A(Foo).Baz;
2913       // [[p]]
2914     }
2915   )";
2916   runDataflow(
2917       Code,
2918       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2919          ASTContext &ASTCtx) {
2920         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2921         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2922 
2923         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2924         ASSERT_THAT(FooDecl, NotNull());
2925 
2926         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2927         ASSERT_THAT(BarDecl, NotNull());
2928 
2929         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2930         ASSERT_THAT(BazDecl, NotNull());
2931 
2932         const auto &FooLoc =
2933             *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2934         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2935         EXPECT_EQ(BarVal, getFieldValue(&FooLoc, *BazDecl, Env));
2936       });
2937 }
2938 
2939 TEST(TransferTest, ResultObjectLocation) {
2940   std::string Code = R"(
2941     struct A {
2942       virtual ~A() = default;
2943     };
2944 
2945     void target() {
2946       0, A();
2947       (void)0; // [[p]]
2948     }
2949   )";
2950   using ast_matchers::binaryOperator;
2951   using ast_matchers::cxxBindTemporaryExpr;
2952   using ast_matchers::cxxTemporaryObjectExpr;
2953   using ast_matchers::exprWithCleanups;
2954   using ast_matchers::has;
2955   using ast_matchers::hasOperatorName;
2956   using ast_matchers::hasRHS;
2957   using ast_matchers::match;
2958   using ast_matchers::selectFirst;
2959   using ast_matchers::traverse;
2960   runDataflow(
2961       Code,
2962       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2963          ASTContext &ASTCtx) {
2964         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2965 
2966         // The expression `0, A()` in the code above produces the following
2967         // structure, consisting of four prvalues of record type.
2968         // `Env.getResultObjectLocation()` should return the same location for
2969         // all of these.
2970         auto MatchResult = match(
2971             traverse(TK_AsIs,
2972                      exprWithCleanups(
2973                          has(binaryOperator(
2974                                  hasOperatorName(","),
2975                                  hasRHS(cxxBindTemporaryExpr(
2976                                             has(cxxTemporaryObjectExpr().bind(
2977                                                 "toe")))
2978                                             .bind("bte")))
2979                                  .bind("comma")))
2980                          .bind("ewc")),
2981             ASTCtx);
2982         auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
2983         ASSERT_NE(TOE, nullptr);
2984         auto *Comma = selectFirst<BinaryOperator>("comma", MatchResult);
2985         ASSERT_NE(Comma, nullptr);
2986         auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
2987         ASSERT_NE(EWC, nullptr);
2988         auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
2989         ASSERT_NE(BTE, nullptr);
2990 
2991         RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
2992         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*Comma));
2993         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
2994         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
2995       });
2996 }
2997 
2998 TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {
2999   std::string Code = R"(
3000     struct Inner {};
3001     struct Outer {
3002         Inner I = {};
3003     };
3004 
3005     void funcWithDefaultArg(Outer O = {});
3006     void target() {
3007       funcWithDefaultArg();
3008       // [[p]]
3009     }
3010   )";
3011 
3012   using ast_matchers::cxxDefaultArgExpr;
3013   using ast_matchers::match;
3014   using ast_matchers::selectFirst;
3015   runDataflow(
3016       Code,
3017       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3018          ASTContext &ASTCtx) {
3019         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3020 
3021         auto *DefaultArg = selectFirst<CXXDefaultArgExpr>(
3022             "default_arg",
3023             match(cxxDefaultArgExpr().bind("default_arg"), ASTCtx));
3024         ASSERT_NE(DefaultArg, nullptr);
3025 
3026         // The values for default arguments aren't modeled; we merely verify
3027         // that we can get a result object location for a default arg.
3028         Env.getResultObjectLocation(*DefaultArg);
3029       });
3030 }
3031 
3032 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
3033   std::string Code = R"(
3034     struct S {};
3035     struct target {
3036       target () {
3037         (void)0;
3038         // [[p]]
3039       }
3040       S s = {};
3041     };
3042   )";
3043 
3044   using ast_matchers::cxxCtorInitializer;
3045   using ast_matchers::match;
3046   using ast_matchers::selectFirst;
3047   runDataflow(
3048       Code,
3049       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3050          ASTContext &ASTCtx) {
3051         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3052 
3053         const ValueDecl *SField = findValueDecl(ASTCtx, "s");
3054 
3055         auto *CtorInit = selectFirst<CXXCtorInitializer>(
3056             "ctor_initializer",
3057             match(cxxCtorInitializer().bind("ctor_initializer"), ASTCtx));
3058         ASSERT_NE(CtorInit, nullptr);
3059 
3060         auto *DefaultInit = cast<CXXDefaultInitExpr>(CtorInit->getInit());
3061 
3062         RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
3063 
3064         EXPECT_EQ(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
3065       });
3066 }
3067 
3068 // This test ensures that CXXOperatorCallExpr returning prvalues are correctly
3069 // handled by the transfer functions, especially that `getResultObjectLocation`
3070 // correctly returns a storage location for those.
3071 TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
3072   std::string Code = R"(
3073     struct A {
3074       A operator+(int);
3075     };
3076 
3077     void target() {
3078       A a;
3079       a + 3;
3080       (void)0; // [[p]]
3081     }
3082   )";
3083   using ast_matchers::cxxOperatorCallExpr;
3084   using ast_matchers::match;
3085   using ast_matchers::selectFirst;
3086   using ast_matchers::traverse;
3087   runDataflow(
3088       Code,
3089       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3090          ASTContext &ASTCtx) {
3091         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3092 
3093         auto *CallExpr = selectFirst<CXXOperatorCallExpr>(
3094             "call_expr",
3095             match(cxxOperatorCallExpr().bind("call_expr"), ASTCtx));
3096 
3097         EXPECT_NE(&Env.getResultObjectLocation(*CallExpr), nullptr);
3098       });
3099 }
3100 
3101 TEST(TransferTest, ResultObjectLocationForInitListExpr) {
3102   std::string Code = R"cc(
3103     struct Inner {};
3104 
3105     struct Outer { Inner I; };
3106 
3107     void target() {
3108       Outer O = { Inner() };
3109       // [[p]]
3110     }
3111   )cc";
3112   using ast_matchers::asString;
3113   using ast_matchers::cxxConstructExpr;
3114   using ast_matchers::hasType;
3115   using ast_matchers::match;
3116   using ast_matchers::selectFirst;
3117   using ast_matchers::traverse;
3118   runDataflow(
3119       Code,
3120       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3121          ASTContext &ASTCtx) {
3122         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3123 
3124         auto *Construct = selectFirst<CXXConstructExpr>(
3125             "construct",
3126             match(
3127                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3128                 ASTCtx));
3129 
3130         EXPECT_EQ(
3131             &Env.getResultObjectLocation(*Construct),
3132             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3133                          "I", ASTCtx));
3134       });
3135 }
3136 
3137 TEST(TransferTest, ResultObjectLocationForParenInitListExpr) {
3138   std::string Code = R"cc(
3139     struct Inner {};
3140 
3141     struct Outer { Inner I; };
3142 
3143     void target() {
3144       Outer O((Inner()));
3145       // [[p]]
3146     }
3147   )cc";
3148   using ast_matchers::asString;
3149   using ast_matchers::cxxConstructExpr;
3150   using ast_matchers::hasType;
3151   using ast_matchers::match;
3152   using ast_matchers::selectFirst;
3153   using ast_matchers::traverse;
3154   runDataflow(
3155       Code,
3156       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3157          ASTContext &ASTCtx) {
3158         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3159 
3160         auto *Construct = selectFirst<CXXConstructExpr>(
3161             "construct",
3162             match(
3163                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3164                 ASTCtx));
3165 
3166         EXPECT_EQ(
3167             &Env.getResultObjectLocation(*Construct),
3168             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3169                          "I", ASTCtx));
3170       },
3171       LangStandard::lang_cxx20);
3172 }
3173 
3174 // Check that the `std::strong_ordering` object returned by builtin `<=>` has a
3175 // correctly modeled result object location.
3176 TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {
3177   std::string Code = R"(
3178     namespace std {
3179       // This is the minimal definition required to get
3180       // `Sema::CheckComparisonCategoryType()` to accept this fake.
3181       struct strong_ordering {
3182         enum class ordering { less, equal, greater };
3183         ordering o;
3184         static const strong_ordering less;
3185         static const strong_ordering equivalent;
3186         static const strong_ordering equal;
3187         static const strong_ordering greater;
3188       };
3189 
3190       inline constexpr strong_ordering strong_ordering::less =
3191         { strong_ordering::ordering::less };
3192       inline constexpr strong_ordering strong_ordering::equal =
3193         { strong_ordering::ordering::equal };
3194       inline constexpr strong_ordering strong_ordering::equivalent =
3195         { strong_ordering::ordering::equal };
3196       inline constexpr strong_ordering strong_ordering::greater =
3197         { strong_ordering::ordering::greater };
3198     }
3199     void target(int i, int j) {
3200       auto ordering = i <=> j;
3201       // [[p]]
3202     }
3203   )";
3204   using ast_matchers::binaryOperator;
3205   using ast_matchers::hasOperatorName;
3206   using ast_matchers::match;
3207   using ast_matchers::selectFirst;
3208   using ast_matchers::traverse;
3209   runDataflow(
3210       Code,
3211       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3212          ASTContext &ASTCtx) {
3213         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3214 
3215         auto *Spaceship = selectFirst<BinaryOperator>(
3216             "op",
3217             match(binaryOperator(hasOperatorName("<=>")).bind("op"), ASTCtx));
3218 
3219         EXPECT_EQ(
3220             &Env.getResultObjectLocation(*Spaceship),
3221             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "ordering"));
3222       },
3223       LangStandard::lang_cxx20);
3224 }
3225 
3226 TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {
3227   std::string Code = R"(
3228     namespace std {
3229     template <typename T>
3230     struct initializer_list {};
3231     } // namespace std
3232 
3233     void target() {
3234       std::initializer_list<int> list = {1};
3235       // [[p]]
3236     }
3237   )";
3238 
3239   using ast_matchers::cxxStdInitializerListExpr;
3240   using ast_matchers::match;
3241   using ast_matchers::selectFirst;
3242   runDataflow(
3243       Code,
3244       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3245          ASTContext &ASTCtx) {
3246         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3247 
3248         auto *StdInitList = selectFirst<CXXStdInitializerListExpr>(
3249             "std_init_list",
3250             match(cxxStdInitializerListExpr().bind("std_init_list"), ASTCtx));
3251         ASSERT_NE(StdInitList, nullptr);
3252 
3253         EXPECT_EQ(&Env.getResultObjectLocation(*StdInitList),
3254                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "list"));
3255       });
3256 }
3257 
3258 TEST(TransferTest, ResultObjectLocationForStmtExpr) {
3259   std::string Code = R"(
3260     struct S {};
3261     void target() {
3262       S s = ({ S(); });
3263       // [[p]]
3264     }
3265   )";
3266   using ast_matchers::cxxConstructExpr;
3267   using ast_matchers::match;
3268   using ast_matchers::selectFirst;
3269   using ast_matchers::traverse;
3270   runDataflow(
3271       Code,
3272       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3273          ASTContext &ASTCtx) {
3274         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3275 
3276         auto *Construct = selectFirst<CXXConstructExpr>(
3277             "construct", match(cxxConstructExpr().bind("construct"), ASTCtx));
3278 
3279         EXPECT_EQ(&Env.getResultObjectLocation(*Construct),
3280                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3281       });
3282 }
3283 
3284 TEST(TransferTest, ResultObjectLocationForBuiltinBitCastExpr) {
3285   std::string Code = R"(
3286     struct S { int i; };
3287     void target(int i) {
3288       S s = __builtin_bit_cast(S, i);
3289       // [[p]]
3290     }
3291   )";
3292   using ast_matchers::explicitCastExpr;
3293   using ast_matchers::match;
3294   using ast_matchers::selectFirst;
3295   using ast_matchers::traverse;
3296   runDataflow(
3297       Code,
3298       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3299          ASTContext &ASTCtx) {
3300         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3301 
3302         auto *BuiltinBitCast = selectFirst<BuiltinBitCastExpr>(
3303             "cast", match(explicitCastExpr().bind("cast"), ASTCtx));
3304 
3305         EXPECT_EQ(&Env.getResultObjectLocation(*BuiltinBitCast),
3306                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3307       });
3308 }
3309 
3310 TEST(TransferTest, ResultObjectLocationPropagatesThroughConditionalOperator) {
3311   std::string Code = R"(
3312     struct A {
3313       A(int);
3314     };
3315 
3316     void target(bool b) {
3317       A a = b ? A(0) : A(1);
3318       (void)0; // [[p]]
3319     }
3320   )";
3321   using ast_matchers::cxxConstructExpr;
3322   using ast_matchers::equals;
3323   using ast_matchers::hasArgument;
3324   using ast_matchers::integerLiteral;
3325   using ast_matchers::match;
3326   using ast_matchers::selectFirst;
3327   using ast_matchers::traverse;
3328   runDataflow(
3329       Code,
3330       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3331          ASTContext &ASTCtx) {
3332         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3333 
3334         auto *ConstructExpr0 = selectFirst<CXXConstructExpr>(
3335             "construct",
3336             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(0))))
3337                       .bind("construct"),
3338                   ASTCtx));
3339         auto *ConstructExpr1 = selectFirst<CXXConstructExpr>(
3340             "construct",
3341             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(1))))
3342                       .bind("construct"),
3343                   ASTCtx));
3344 
3345         auto &ALoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "a");
3346         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr0), &ALoc);
3347         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr1), &ALoc);
3348       });
3349 }
3350 
3351 TEST(TransferTest, StaticCast) {
3352   std::string Code = R"(
3353     void target(int Foo) {
3354       int Bar = static_cast<int>(Foo);
3355       // [[p]]
3356     }
3357   )";
3358   runDataflow(
3359       Code,
3360       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3361          ASTContext &ASTCtx) {
3362         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3363         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3364 
3365         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3366         ASSERT_THAT(FooDecl, NotNull());
3367 
3368         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3369         ASSERT_THAT(BarDecl, NotNull());
3370 
3371         const auto *FooVal = Env.getValue(*FooDecl);
3372         const auto *BarVal = Env.getValue(*BarDecl);
3373         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3374         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3375         EXPECT_EQ(FooVal, BarVal);
3376       });
3377 }
3378 
3379 TEST(TransferTest, IntegralCast) {
3380   std::string Code = R"(
3381     void target(int Foo) {
3382       long Bar = Foo;
3383       // [[p]]
3384     }
3385   )";
3386   runDataflow(
3387       Code,
3388       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3389          ASTContext &ASTCtx) {
3390         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3391         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3392 
3393         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3394         ASSERT_THAT(FooDecl, NotNull());
3395 
3396         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3397         ASSERT_THAT(BarDecl, NotNull());
3398 
3399         const auto *FooVal = Env.getValue(*FooDecl);
3400         const auto *BarVal = Env.getValue(*BarDecl);
3401         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3402         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3403         EXPECT_EQ(FooVal, BarVal);
3404       });
3405 }
3406 
3407 TEST(TransferTest, IntegraltoBooleanCast) {
3408   std::string Code = R"(
3409     void target(int Foo) {
3410       bool Bar = Foo;
3411       // [[p]]
3412     }
3413   )";
3414   runDataflow(
3415       Code,
3416       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3417          ASTContext &ASTCtx) {
3418         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3419         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3420 
3421         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3422         ASSERT_THAT(FooDecl, NotNull());
3423 
3424         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3425         ASSERT_THAT(BarDecl, NotNull());
3426 
3427         const auto *FooVal = Env.getValue(*FooDecl);
3428         const auto *BarVal = Env.getValue(*BarDecl);
3429         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3430         EXPECT_TRUE(isa<BoolValue>(BarVal));
3431       });
3432 }
3433 
3434 TEST(TransferTest, IntegralToBooleanCastFromBool) {
3435   std::string Code = R"(
3436     void target(bool Foo) {
3437       int Zab = Foo;
3438       bool Bar = Zab;
3439       // [[p]]
3440     }
3441   )";
3442   runDataflow(
3443       Code,
3444       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3445          ASTContext &ASTCtx) {
3446         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3447         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3448 
3449         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3450         ASSERT_THAT(FooDecl, NotNull());
3451 
3452         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3453         ASSERT_THAT(BarDecl, NotNull());
3454 
3455         const auto *FooVal = Env.getValue(*FooDecl);
3456         const auto *BarVal = Env.getValue(*BarDecl);
3457         EXPECT_TRUE(isa<BoolValue>(FooVal));
3458         EXPECT_TRUE(isa<BoolValue>(BarVal));
3459         EXPECT_EQ(FooVal, BarVal);
3460       });
3461 }
3462 
3463 TEST(TransferTest, NullToPointerCast) {
3464   std::string Code = R"(
3465     using my_nullptr_t = decltype(nullptr);
3466     struct Baz {};
3467     void target() {
3468       int *FooX = nullptr;
3469       int *FooY = nullptr;
3470       bool **Bar = nullptr;
3471       Baz *Baz = nullptr;
3472       my_nullptr_t Null = 0;
3473       // [[p]]
3474     }
3475   )";
3476   runDataflow(
3477       Code,
3478       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3479          ASTContext &ASTCtx) {
3480         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3481         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3482 
3483         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
3484         ASSERT_THAT(FooXDecl, NotNull());
3485 
3486         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
3487         ASSERT_THAT(FooYDecl, NotNull());
3488 
3489         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3490         ASSERT_THAT(BarDecl, NotNull());
3491 
3492         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3493         ASSERT_THAT(BazDecl, NotNull());
3494 
3495         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
3496         ASSERT_THAT(NullDecl, NotNull());
3497 
3498         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
3499         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
3500         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3501         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
3502         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
3503 
3504         EXPECT_EQ(FooXVal, FooYVal);
3505         EXPECT_NE(FooXVal, BarVal);
3506         EXPECT_NE(FooXVal, BazVal);
3507         EXPECT_NE(BarVal, BazVal);
3508 
3509         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
3510         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
3511         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
3512 
3513         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
3514         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
3515         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
3516 
3517         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
3518         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
3519         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
3520 
3521         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
3522         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
3523         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
3524       });
3525 }
3526 
3527 TEST(TransferTest, PointerToMemberVariable) {
3528   std::string Code = R"(
3529     struct S {
3530       int i;
3531     };
3532     void target() {
3533       int S::*MemberPointer = &S::i;
3534       // [[p]]
3535     }
3536   )";
3537   runDataflow(
3538       Code,
3539       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3540          ASTContext &ASTCtx) {
3541         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3542 
3543         const ValueDecl *MemberPointerDecl =
3544             findValueDecl(ASTCtx, "MemberPointer");
3545         ASSERT_THAT(MemberPointerDecl, NotNull());
3546         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3547       });
3548 }
3549 
3550 TEST(TransferTest, PointerToMemberFunction) {
3551   std::string Code = R"(
3552     struct S {
3553       void Method();
3554     };
3555     void target() {
3556       void (S::*MemberPointer)() = &S::Method;
3557       // [[p]]
3558     }
3559   )";
3560   runDataflow(
3561       Code,
3562       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3563          ASTContext &ASTCtx) {
3564         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3565 
3566         const ValueDecl *MemberPointerDecl =
3567             findValueDecl(ASTCtx, "MemberPointer");
3568         ASSERT_THAT(MemberPointerDecl, NotNull());
3569         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3570       });
3571 }
3572 
3573 TEST(TransferTest, NullToMemberPointerCast) {
3574   std::string Code = R"(
3575     struct Foo {};
3576     void target() {
3577       int Foo::*MemberPointer = nullptr;
3578       // [[p]]
3579     }
3580   )";
3581   runDataflow(
3582       Code,
3583       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3584          ASTContext &ASTCtx) {
3585         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3586         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3587 
3588         const ValueDecl *MemberPointerDecl =
3589             findValueDecl(ASTCtx, "MemberPointer");
3590         ASSERT_THAT(MemberPointerDecl, NotNull());
3591         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3592       });
3593 }
3594 
3595 TEST(TransferTest, AddrOfValue) {
3596   std::string Code = R"(
3597     void target() {
3598       int Foo;
3599       int *Bar = &Foo;
3600       // [[p]]
3601     }
3602   )";
3603   runDataflow(
3604       Code,
3605       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3606          ASTContext &ASTCtx) {
3607         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3608         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3609 
3610         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3611         ASSERT_THAT(FooDecl, NotNull());
3612 
3613         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3614         ASSERT_THAT(BarDecl, NotNull());
3615 
3616         const auto *FooLoc =
3617             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3618         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3619         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3620       });
3621 }
3622 
3623 TEST(TransferTest, AddrOfReference) {
3624   std::string Code = R"(
3625     void target(int *Foo) {
3626       int *Bar = &(*Foo);
3627       // [[p]]
3628     }
3629   )";
3630   runDataflow(
3631       Code,
3632       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3633          ASTContext &ASTCtx) {
3634         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3635         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3636 
3637         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3638         ASSERT_THAT(FooDecl, NotNull());
3639 
3640         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3641         ASSERT_THAT(BarDecl, NotNull());
3642 
3643         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3644         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3645         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3646       });
3647 }
3648 
3649 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3650   std::string Code = R"(
3651     template <typename T>
3652     void target() {}
3653   )";
3654   ASSERT_THAT_ERROR(
3655       checkDataflowWithNoopAnalysis(Code),
3656       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3657 }
3658 
3659 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3660   std::string Code = R"(
3661     template <typename T>
3662     struct A {
3663       void target() {}
3664     };
3665   )";
3666   ASSERT_THAT_ERROR(
3667       checkDataflowWithNoopAnalysis(Code),
3668       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3669 }
3670 
3671 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3672   std::string Code = R"(
3673     struct A {};
3674 
3675     void target(A Foo, A Bar, bool Cond) {
3676       A Baz = Cond ?  Foo : Bar;
3677       /*[[p]]*/
3678     }
3679   )";
3680   runDataflow(
3681       Code,
3682       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3683          ASTContext &ASTCtx) {
3684         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3685         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3686 
3687         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3688         ASSERT_THAT(FooDecl, NotNull());
3689 
3690         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3691         ASSERT_THAT(BarDecl, NotNull());
3692 
3693         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3694         ASSERT_THAT(BazDecl, NotNull());
3695 
3696         const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
3697         const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
3698 
3699         const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
3700         ASSERT_THAT(BazVal, NotNull());
3701 
3702         EXPECT_NE(BazVal, FooVal);
3703         EXPECT_NE(BazVal, BarVal);
3704       });
3705 }
3706 
3707 TEST(TransferTest, VarDeclInDoWhile) {
3708   std::string Code = R"(
3709     void target(int *Foo) {
3710       do {
3711         int Bar = *Foo;
3712         // [[in_loop]]
3713       } while (false);
3714       (void)0;
3715       // [[after_loop]]
3716     }
3717   )";
3718   runDataflow(
3719       Code,
3720       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3721          ASTContext &ASTCtx) {
3722         const Environment &EnvInLoop =
3723             getEnvironmentAtAnnotation(Results, "in_loop");
3724         const Environment &EnvAfterLoop =
3725             getEnvironmentAtAnnotation(Results, "after_loop");
3726 
3727         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3728         ASSERT_THAT(FooDecl, NotNull());
3729 
3730         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3731         ASSERT_THAT(BarDecl, NotNull());
3732 
3733         const auto *FooVal =
3734             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3735         const auto *FooPointeeVal =
3736             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3737 
3738         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3739         EXPECT_EQ(BarVal, FooPointeeVal);
3740 
3741         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3742       });
3743 }
3744 
3745 TEST(TransferTest, UnreachableAfterWhileTrue) {
3746   std::string Code = R"(
3747     void target() {
3748       while (true) {}
3749       (void)0;
3750       /*[[p]]*/
3751     }
3752   )";
3753   runDataflow(
3754       Code,
3755       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3756          ASTContext &ASTCtx) {
3757         // The node after the while-true is pruned because it is trivially
3758         // known to be unreachable.
3759         ASSERT_TRUE(Results.empty());
3760       });
3761 }
3762 
3763 TEST(TransferTest, AggregateInitialization) {
3764   std::string BracesCode = R"(
3765     struct A {
3766       int Foo;
3767     };
3768 
3769     struct B {
3770       int Bar;
3771       A Baz;
3772       int Qux;
3773     };
3774 
3775     void target(int BarArg, int FooArg, int QuxArg) {
3776       B Quux{BarArg, {FooArg}, QuxArg};
3777       B OtherB;
3778       /*[[p]]*/
3779     }
3780   )";
3781   std::string BraceElisionCode = R"(
3782     struct A {
3783       int Foo;
3784     };
3785 
3786     struct B {
3787       int Bar;
3788       A Baz;
3789       int Qux;
3790     };
3791 
3792     void target(int BarArg, int FooArg, int QuxArg) {
3793       B Quux = {BarArg, FooArg, QuxArg};
3794       B OtherB;
3795       /*[[p]]*/
3796     }
3797   )";
3798   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3799     runDataflow(
3800         Code,
3801         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3802            ASTContext &ASTCtx) {
3803           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3804           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3805 
3806           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3807           ASSERT_THAT(FooDecl, NotNull());
3808 
3809           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3810           ASSERT_THAT(BarDecl, NotNull());
3811 
3812           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3813           ASSERT_THAT(BazDecl, NotNull());
3814 
3815           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3816           ASSERT_THAT(QuxDecl, NotNull());
3817 
3818           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3819           ASSERT_THAT(FooArgDecl, NotNull());
3820 
3821           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3822           ASSERT_THAT(BarArgDecl, NotNull());
3823 
3824           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3825           ASSERT_THAT(QuxArgDecl, NotNull());
3826 
3827           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3828           ASSERT_THAT(QuuxDecl, NotNull());
3829 
3830           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3831           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3832           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3833 
3834           const auto &QuuxLoc =
3835               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3836           const auto &BazLoc =
3837               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3838 
3839           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3840           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3841           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3842 
3843           // Check that fields initialized in an initializer list are always
3844           // modeled in other instances of the same type.
3845           const auto &OtherBLoc =
3846               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3847           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3848           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3849           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3850         });
3851   }
3852 }
3853 
3854 TEST(TransferTest, AggregateInitializationReferenceField) {
3855   std::string Code = R"(
3856     struct S {
3857       int &RefField;
3858     };
3859 
3860     void target(int i) {
3861       S s = { i };
3862       /*[[p]]*/
3863     }
3864   )";
3865   runDataflow(
3866       Code,
3867       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3868          ASTContext &ASTCtx) {
3869         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3870 
3871         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3872 
3873         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3874         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3875 
3876         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3877       });
3878 }
3879 
3880 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3881   std::string Code = R"(
3882     struct S {
3883       int i1;
3884       int i2;
3885     };
3886 
3887     void target(int i) {
3888       S s = { i };
3889       /*[[p]]*/
3890     }
3891   )";
3892   runDataflow(
3893       Code,
3894       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3895          ASTContext &ASTCtx) {
3896         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3897 
3898         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3899         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3900 
3901         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3902 
3903         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3904         auto &I1Value =
3905             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3906         EXPECT_EQ(&I1Value, &IValue);
3907         auto &I2Value =
3908             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3909         EXPECT_NE(&I2Value, &IValue);
3910       });
3911 }
3912 
3913 TEST(TransferTest, AggregateInitializationFunctionPointer) {
3914   // This is a repro for an assertion failure.
3915   // nullptr takes on the type of a const function pointer, but its type was
3916   // asserted to be equal to the *unqualified* type of Field, which no longer
3917   // included the const.
3918   std::string Code = R"(
3919     struct S {
3920       void (*const Field)();
3921     };
3922 
3923     void target() {
3924       S s{nullptr};
3925     }
3926   )";
3927   runDataflow(
3928       Code,
3929       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3930          ASTContext &ASTCtx) {});
3931 }
3932 
3933 TEST(TransferTest, AssignToUnionMember) {
3934   std::string Code = R"(
3935     union A {
3936       int Foo;
3937     };
3938 
3939     void target(int Bar) {
3940       A Baz;
3941       Baz.Foo = Bar;
3942       // [[p]]
3943     }
3944   )";
3945   runDataflow(
3946       Code,
3947       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3948          ASTContext &ASTCtx) {
3949         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3950         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3951 
3952         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3953         ASSERT_THAT(BazDecl, NotNull());
3954         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3955 
3956         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3957         FieldDecl *FooDecl = nullptr;
3958         for (FieldDecl *Field : BazFields) {
3959           if (Field->getNameAsString() == "Foo") {
3960             FooDecl = Field;
3961           } else {
3962             FAIL() << "Unexpected field: " << Field->getNameAsString();
3963           }
3964         }
3965         ASSERT_THAT(FooDecl, NotNull());
3966 
3967         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
3968             Env.getStorageLocation(*BazDecl));
3969         ASSERT_THAT(BazLoc, NotNull());
3970         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
3971 
3972         const auto *FooVal =
3973             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
3974 
3975         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3976         ASSERT_THAT(BarDecl, NotNull());
3977         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
3978         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3979 
3980         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
3981       });
3982 }
3983 
3984 TEST(TransferTest, AssignFromBoolLiteral) {
3985   std::string Code = R"(
3986     void target() {
3987       bool Foo = true;
3988       bool Bar = false;
3989       // [[p]]
3990     }
3991   )";
3992   runDataflow(
3993       Code,
3994       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3995          ASTContext &ASTCtx) {
3996         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3997         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3998 
3999         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4000         ASSERT_THAT(FooDecl, NotNull());
4001 
4002         const auto *FooVal =
4003             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4004         ASSERT_THAT(FooVal, NotNull());
4005 
4006         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4007         ASSERT_THAT(BarDecl, NotNull());
4008 
4009         const auto *BarVal =
4010             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4011         ASSERT_THAT(BarVal, NotNull());
4012 
4013         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
4014         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
4015       });
4016 }
4017 
4018 TEST(TransferTest, AssignFromCompositeBoolExpression) {
4019   {
4020     std::string Code = R"(
4021     void target(bool Foo, bool Bar, bool Qux) {
4022       bool Baz = (Foo) && (Bar || Qux);
4023       // [[p]]
4024     }
4025   )";
4026     runDataflow(
4027         Code,
4028         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4029            ASTContext &ASTCtx) {
4030           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4031           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4032 
4033           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4034           ASSERT_THAT(FooDecl, NotNull());
4035 
4036           const auto *FooVal =
4037               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4038           ASSERT_THAT(FooVal, NotNull());
4039 
4040           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4041           ASSERT_THAT(BarDecl, NotNull());
4042 
4043           const auto *BarVal =
4044               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4045           ASSERT_THAT(BarVal, NotNull());
4046 
4047           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4048           ASSERT_THAT(QuxDecl, NotNull());
4049 
4050           const auto *QuxVal =
4051               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4052           ASSERT_THAT(QuxVal, NotNull());
4053 
4054           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4055           ASSERT_THAT(BazDecl, NotNull());
4056 
4057           const auto *BazVal =
4058               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4059           ASSERT_THAT(BazVal, NotNull());
4060           auto &A = Env.arena();
4061           EXPECT_EQ(&BazVal->formula(),
4062                     &A.makeAnd(FooVal->formula(),
4063                                A.makeOr(BarVal->formula(), QuxVal->formula())));
4064         });
4065   }
4066 
4067   {
4068     std::string Code = R"(
4069     void target(bool Foo, bool Bar, bool Qux) {
4070       bool Baz = (Foo && Qux) || (Bar);
4071       // [[p]]
4072     }
4073   )";
4074     runDataflow(
4075         Code,
4076         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4077            ASTContext &ASTCtx) {
4078           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4079           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4080 
4081           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4082           ASSERT_THAT(FooDecl, NotNull());
4083 
4084           const auto *FooVal =
4085               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4086           ASSERT_THAT(FooVal, NotNull());
4087 
4088           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4089           ASSERT_THAT(BarDecl, NotNull());
4090 
4091           const auto *BarVal =
4092               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4093           ASSERT_THAT(BarVal, NotNull());
4094 
4095           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4096           ASSERT_THAT(QuxDecl, NotNull());
4097 
4098           const auto *QuxVal =
4099               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4100           ASSERT_THAT(QuxVal, NotNull());
4101 
4102           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4103           ASSERT_THAT(BazDecl, NotNull());
4104 
4105           const auto *BazVal =
4106               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4107           ASSERT_THAT(BazVal, NotNull());
4108           auto &A = Env.arena();
4109           EXPECT_EQ(&BazVal->formula(),
4110                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
4111                               BarVal->formula()));
4112         });
4113   }
4114 
4115   {
4116     std::string Code = R"(
4117       void target(bool A, bool B, bool C, bool D) {
4118         bool Foo = ((A && B) && C) && D;
4119         // [[p]]
4120       }
4121     )";
4122     runDataflow(
4123         Code,
4124         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4125            ASTContext &ASTCtx) {
4126           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4127           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4128 
4129           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
4130           ASSERT_THAT(ADecl, NotNull());
4131 
4132           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
4133           ASSERT_THAT(AVal, NotNull());
4134 
4135           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4136           ASSERT_THAT(BDecl, NotNull());
4137 
4138           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
4139           ASSERT_THAT(BVal, NotNull());
4140 
4141           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4142           ASSERT_THAT(CDecl, NotNull());
4143 
4144           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
4145           ASSERT_THAT(CVal, NotNull());
4146 
4147           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
4148           ASSERT_THAT(DDecl, NotNull());
4149 
4150           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
4151           ASSERT_THAT(DVal, NotNull());
4152 
4153           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4154           ASSERT_THAT(FooDecl, NotNull());
4155 
4156           const auto *FooVal =
4157               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4158           ASSERT_THAT(FooVal, NotNull());
4159           auto &A = Env.arena();
4160           EXPECT_EQ(
4161               &FooVal->formula(),
4162               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
4163                                    CVal->formula()),
4164                          DVal->formula()));
4165         });
4166   }
4167 }
4168 
4169 TEST(TransferTest, AssignFromBoolNegation) {
4170   std::string Code = R"(
4171     void target() {
4172       bool Foo = true;
4173       bool Bar = !(Foo);
4174       // [[p]]
4175     }
4176   )";
4177   runDataflow(
4178       Code,
4179       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4180          ASTContext &ASTCtx) {
4181         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4182         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4183 
4184         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4185         ASSERT_THAT(FooDecl, NotNull());
4186 
4187         const auto *FooVal =
4188             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4189         ASSERT_THAT(FooVal, NotNull());
4190 
4191         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4192         ASSERT_THAT(BarDecl, NotNull());
4193 
4194         const auto *BarVal =
4195             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4196         ASSERT_THAT(BarVal, NotNull());
4197         auto &A = Env.arena();
4198         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
4199       });
4200 }
4201 
4202 TEST(TransferTest, BuiltinExpect) {
4203   std::string Code = R"(
4204     void target(long Foo) {
4205       long Bar = __builtin_expect(Foo, true);
4206       /*[[p]]*/
4207     }
4208   )";
4209   runDataflow(
4210       Code,
4211       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4212          ASTContext &ASTCtx) {
4213         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4214         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4215 
4216         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4217         ASSERT_THAT(FooDecl, NotNull());
4218 
4219         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4220         ASSERT_THAT(BarDecl, NotNull());
4221 
4222         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4223       });
4224 }
4225 
4226 // `__builtin_expect` takes and returns a `long` argument, so other types
4227 // involve casts. This verifies that we identify the input and output in that
4228 // case.
4229 TEST(TransferTest, BuiltinExpectBoolArg) {
4230   std::string Code = R"(
4231     void target(bool Foo) {
4232       bool Bar = __builtin_expect(Foo, true);
4233       /*[[p]]*/
4234     }
4235   )";
4236   runDataflow(
4237       Code,
4238       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4239          ASTContext &ASTCtx) {
4240         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4241         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4242 
4243         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4244         ASSERT_THAT(FooDecl, NotNull());
4245 
4246         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4247         ASSERT_THAT(BarDecl, NotNull());
4248 
4249         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4250       });
4251 }
4252 
4253 TEST(TransferTest, BuiltinUnreachable) {
4254   std::string Code = R"(
4255     void target(bool Foo) {
4256       bool Bar = false;
4257       if (Foo)
4258         Bar = Foo;
4259       else
4260         __builtin_unreachable();
4261       (void)0;
4262       /*[[p]]*/
4263     }
4264   )";
4265   runDataflow(
4266       Code,
4267       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4268          ASTContext &ASTCtx) {
4269         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4270         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4271 
4272         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4273         ASSERT_THAT(FooDecl, NotNull());
4274 
4275         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4276         ASSERT_THAT(BarDecl, NotNull());
4277 
4278         // `__builtin_unreachable` promises that the code is
4279         // unreachable, so the compiler treats the "then" branch as the
4280         // only possible predecessor of this statement.
4281         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4282       });
4283 }
4284 
4285 TEST(TransferTest, BuiltinTrap) {
4286   std::string Code = R"(
4287     void target(bool Foo) {
4288       bool Bar = false;
4289       if (Foo)
4290         Bar = Foo;
4291       else
4292         __builtin_trap();
4293       (void)0;
4294       /*[[p]]*/
4295     }
4296   )";
4297   runDataflow(
4298       Code,
4299       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4300          ASTContext &ASTCtx) {
4301         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4302         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4303 
4304         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4305         ASSERT_THAT(FooDecl, NotNull());
4306 
4307         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4308         ASSERT_THAT(BarDecl, NotNull());
4309 
4310         // `__builtin_trap` ensures program termination, so only the
4311         // "then" branch is a predecessor of this statement.
4312         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4313       });
4314 }
4315 
4316 TEST(TransferTest, BuiltinDebugTrap) {
4317   std::string Code = R"(
4318     void target(bool Foo) {
4319       bool Bar = false;
4320       if (Foo)
4321         Bar = Foo;
4322       else
4323         __builtin_debugtrap();
4324       (void)0;
4325       /*[[p]]*/
4326     }
4327   )";
4328   runDataflow(
4329       Code,
4330       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4331          ASTContext &ASTCtx) {
4332         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4333         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4334 
4335         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4336         ASSERT_THAT(FooDecl, NotNull());
4337 
4338         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4339         ASSERT_THAT(BarDecl, NotNull());
4340 
4341         // `__builtin_debugtrap` doesn't ensure program termination.
4342         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4343       });
4344 }
4345 
4346 TEST(TransferTest, StaticIntSingleVarDecl) {
4347   std::string Code = R"(
4348     void target() {
4349       static int Foo;
4350       // [[p]]
4351     }
4352   )";
4353   runDataflow(
4354       Code,
4355       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4356          ASTContext &ASTCtx) {
4357         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4358         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4359 
4360         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4361         ASSERT_THAT(FooDecl, NotNull());
4362 
4363         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4364         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4365 
4366         const Value *FooVal = Env.getValue(*FooLoc);
4367         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4368       });
4369 }
4370 
4371 TEST(TransferTest, StaticIntGroupVarDecl) {
4372   std::string Code = R"(
4373     void target() {
4374       static int Foo, Bar;
4375       (void)0;
4376       // [[p]]
4377     }
4378   )";
4379   runDataflow(
4380       Code,
4381       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4382          ASTContext &ASTCtx) {
4383         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4384         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4385 
4386         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4387         ASSERT_THAT(FooDecl, NotNull());
4388 
4389         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4390         ASSERT_THAT(BarDecl, NotNull());
4391 
4392         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4393         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4394 
4395         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4396         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4397 
4398         const Value *FooVal = Env.getValue(*FooLoc);
4399         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4400 
4401         const Value *BarVal = Env.getValue(*BarLoc);
4402         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
4403 
4404         EXPECT_NE(FooVal, BarVal);
4405       });
4406 }
4407 
4408 TEST(TransferTest, GlobalIntVarDecl) {
4409   std::string Code = R"(
4410     static int Foo;
4411 
4412     void target() {
4413       int Bar = Foo;
4414       int Baz = Foo;
4415       // [[p]]
4416     }
4417   )";
4418   runDataflow(
4419       Code,
4420       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4421          ASTContext &ASTCtx) {
4422         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4423         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4424 
4425         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4426         ASSERT_THAT(BarDecl, NotNull());
4427 
4428         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4429         ASSERT_THAT(BazDecl, NotNull());
4430 
4431         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4432         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4433         EXPECT_EQ(BarVal, BazVal);
4434       });
4435 }
4436 
4437 TEST(TransferTest, StaticMemberIntVarDecl) {
4438   std::string Code = R"(
4439     struct A {
4440       static int Foo;
4441     };
4442 
4443     void target(A a) {
4444       int Bar = a.Foo;
4445       int Baz = a.Foo;
4446       // [[p]]
4447     }
4448   )";
4449   runDataflow(
4450       Code,
4451       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4452          ASTContext &ASTCtx) {
4453         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4454         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4455 
4456         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4457         ASSERT_THAT(BarDecl, NotNull());
4458 
4459         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4460         ASSERT_THAT(BazDecl, NotNull());
4461 
4462         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4463         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4464         EXPECT_EQ(BarVal, BazVal);
4465       });
4466 }
4467 
4468 TEST(TransferTest, StaticMemberRefVarDecl) {
4469   std::string Code = R"(
4470     struct A {
4471       static int &Foo;
4472     };
4473 
4474     void target(A a) {
4475       int Bar = a.Foo;
4476       int Baz = a.Foo;
4477       // [[p]]
4478     }
4479   )";
4480   runDataflow(
4481       Code,
4482       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4483          ASTContext &ASTCtx) {
4484         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4485         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4486 
4487         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4488         ASSERT_THAT(BarDecl, NotNull());
4489 
4490         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4491         ASSERT_THAT(BazDecl, NotNull());
4492 
4493         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4494         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4495         EXPECT_EQ(BarVal, BazVal);
4496       });
4497 }
4498 
4499 TEST(TransferTest, AssignMemberBeforeCopy) {
4500   std::string Code = R"(
4501     struct A {
4502       int Foo;
4503     };
4504 
4505     void target() {
4506       A A1;
4507       A A2;
4508       int Bar;
4509       A1.Foo = Bar;
4510       A2 = A1;
4511       // [[p]]
4512     }
4513   )";
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 *FooDecl = findValueDecl(ASTCtx, "Foo");
4522         ASSERT_THAT(FooDecl, NotNull());
4523 
4524         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4525         ASSERT_THAT(BarDecl, NotNull());
4526 
4527         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
4528         ASSERT_THAT(A1Decl, NotNull());
4529 
4530         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
4531         ASSERT_THAT(A2Decl, NotNull());
4532 
4533         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4534 
4535         const auto &A2Loc =
4536             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
4537         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
4538       });
4539 }
4540 
4541 TEST(TransferTest, BooleanEquality) {
4542   std::string Code = R"(
4543     void target(bool Bar) {
4544       bool Foo = true;
4545       if (Bar == Foo) {
4546         (void)0;
4547         /*[[p-then]]*/
4548       } else {
4549         (void)0;
4550         /*[[p-else]]*/
4551       }
4552     }
4553   )";
4554   runDataflow(
4555       Code,
4556       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4557          ASTContext &ASTCtx) {
4558         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4559         const Environment &EnvThen =
4560             getEnvironmentAtAnnotation(Results, "p-then");
4561         const Environment &EnvElse =
4562             getEnvironmentAtAnnotation(Results, "p-else");
4563 
4564         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4565         ASSERT_THAT(BarDecl, NotNull());
4566 
4567         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4568         EXPECT_TRUE(EnvThen.proves(BarValThen));
4569 
4570         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4571         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4572       });
4573 }
4574 
4575 TEST(TransferTest, BooleanInequality) {
4576   std::string Code = R"(
4577     void target(bool Bar) {
4578       bool Foo = true;
4579       if (Bar != Foo) {
4580         (void)0;
4581         /*[[p-then]]*/
4582       } else {
4583         (void)0;
4584         /*[[p-else]]*/
4585       }
4586     }
4587   )";
4588   runDataflow(
4589       Code,
4590       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4591          ASTContext &ASTCtx) {
4592         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4593         const Environment &EnvThen =
4594             getEnvironmentAtAnnotation(Results, "p-then");
4595         const Environment &EnvElse =
4596             getEnvironmentAtAnnotation(Results, "p-else");
4597 
4598         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4599         ASSERT_THAT(BarDecl, NotNull());
4600 
4601         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4602         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4603 
4604         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4605         EXPECT_TRUE(EnvElse.proves(BarValElse));
4606       });
4607 }
4608 
4609 TEST(TransferTest, IntegerLiteralEquality) {
4610   std::string Code = R"(
4611     void target() {
4612       bool equal = (42 == 42);
4613       // [[p]]
4614     }
4615   )";
4616   runDataflow(
4617       Code,
4618       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4619          ASTContext &ASTCtx) {
4620         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4621 
4622         auto &Equal =
4623             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4624         EXPECT_TRUE(Env.proves(Equal));
4625       });
4626 }
4627 
4628 TEST(TransferTest, CorrelatedBranches) {
4629   std::string Code = R"(
4630     void target(bool B, bool C) {
4631       if (B) {
4632         return;
4633       }
4634       (void)0;
4635       /*[[p0]]*/
4636       if (C) {
4637         B = true;
4638         /*[[p1]]*/
4639       }
4640       if (B) {
4641         (void)0;
4642         /*[[p2]]*/
4643       }
4644     }
4645   )";
4646   runDataflow(
4647       Code,
4648       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4649          ASTContext &ASTCtx) {
4650         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4651 
4652         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4653         ASSERT_THAT(CDecl, NotNull());
4654 
4655         {
4656           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4657           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4658           ASSERT_THAT(BDecl, NotNull());
4659           auto &BVal = getFormula(*BDecl, Env);
4660 
4661           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4662         }
4663 
4664         {
4665           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4666           auto &CVal = getFormula(*CDecl, Env);
4667           EXPECT_TRUE(Env.proves(CVal));
4668         }
4669 
4670         {
4671           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4672           auto &CVal = getFormula(*CDecl, Env);
4673           EXPECT_TRUE(Env.proves(CVal));
4674         }
4675       });
4676 }
4677 
4678 TEST(TransferTest, LoopWithAssignmentConverges) {
4679   std::string Code = R"(
4680     bool foo();
4681 
4682     void target() {
4683        do {
4684         bool Bar = foo();
4685         if (Bar) break;
4686         (void)Bar;
4687         /*[[p]]*/
4688       } while (true);
4689     }
4690   )";
4691   // The key property that we are verifying is implicit in `runDataflow` --
4692   // namely, that the analysis succeeds, rather than hitting the maximum number
4693   // of iterations.
4694   runDataflow(
4695       Code,
4696       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4697          ASTContext &ASTCtx) {
4698         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4699         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4700 
4701         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4702         ASSERT_THAT(BarDecl, NotNull());
4703 
4704         auto &BarVal = getFormula(*BarDecl, Env);
4705         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4706       });
4707 }
4708 
4709 TEST(TransferTest, LoopWithStagedAssignments) {
4710   std::string Code = R"(
4711     bool foo();
4712 
4713     void target() {
4714       bool Bar = false;
4715       bool Err = false;
4716       while (foo()) {
4717         if (Bar)
4718           Err = true;
4719         Bar = true;
4720         /*[[p]]*/
4721       }
4722     }
4723   )";
4724   runDataflow(
4725       Code,
4726       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4727          ASTContext &ASTCtx) {
4728         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4729         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4730 
4731         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4732         ASSERT_THAT(BarDecl, NotNull());
4733         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4734         ASSERT_THAT(ErrDecl, NotNull());
4735 
4736         auto &BarVal = getFormula(*BarDecl, Env);
4737         auto &ErrVal = getFormula(*ErrDecl, Env);
4738         EXPECT_TRUE(Env.proves(BarVal));
4739         // An unsound analysis, for example only evaluating the loop once, can
4740         // conclude that `Err` is false. So, we test that this conclusion is not
4741         // reached.
4742         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4743       });
4744 }
4745 
4746 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4747   std::string Code = R"(
4748     bool &foo();
4749 
4750     void target() {
4751        do {
4752         bool& Bar = foo();
4753         if (Bar) break;
4754         (void)Bar;
4755         /*[[p]]*/
4756       } while (true);
4757     }
4758   )";
4759   // The key property that we are verifying is that the analysis succeeds,
4760   // rather than hitting the maximum number of iterations.
4761   runDataflow(
4762       Code,
4763       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4764          ASTContext &ASTCtx) {
4765         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4766         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4767 
4768         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4769         ASSERT_THAT(BarDecl, NotNull());
4770 
4771         auto &BarVal = getFormula(*BarDecl, Env);
4772         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4773       });
4774 }
4775 
4776 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4777   std::string Code = R"(
4778     struct Lookup {
4779       int x;
4780     };
4781 
4782     void target(Lookup val, bool b) {
4783       const Lookup* l = nullptr;
4784       while (b) {
4785         l = &val;
4786         /*[[p-inner]]*/
4787       }
4788       (void)0;
4789       /*[[p-outer]]*/
4790     }
4791   )";
4792   // The key property that we are verifying is implicit in `runDataflow` --
4793   // namely, that the analysis succeeds, rather than hitting the maximum number
4794   // of iterations.
4795   runDataflow(
4796       Code,
4797       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4798          ASTContext &ASTCtx) {
4799         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4800         const Environment &InnerEnv =
4801             getEnvironmentAtAnnotation(Results, "p-inner");
4802         const Environment &OuterEnv =
4803             getEnvironmentAtAnnotation(Results, "p-outer");
4804 
4805         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4806         ASSERT_THAT(ValDecl, NotNull());
4807 
4808         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4809         ASSERT_THAT(LDecl, NotNull());
4810 
4811         // Inner.
4812         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4813         ASSERT_THAT(LVal, NotNull());
4814 
4815         EXPECT_EQ(&LVal->getPointeeLoc(),
4816                   InnerEnv.getStorageLocation(*ValDecl));
4817 
4818         // Outer.
4819         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4820         ASSERT_THAT(LVal, NotNull());
4821 
4822         // The loop body may not have been executed, so we should not conclude
4823         // that `l` points to `val`.
4824         EXPECT_NE(&LVal->getPointeeLoc(),
4825                   OuterEnv.getStorageLocation(*ValDecl));
4826       });
4827 }
4828 
4829 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4830   std::string Code = R"cc(
4831     bool some_condition();
4832 
4833     void target(int i1, int i2) {
4834       int *p = &i1;
4835       while (true) {
4836         (void)*p;
4837         if (some_condition())
4838           p = &i1;
4839         else
4840           p = &i2;
4841       }
4842     }
4843   )cc";
4844   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4845 }
4846 
4847 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4848   std::string Code = R"cc(
4849     struct Lookup {
4850       int x;
4851     };
4852 
4853     bool some_condition();
4854 
4855     void target(Lookup l1, Lookup l2) {
4856       Lookup *l = &l1;
4857       while (true) {
4858         (void)l->x;
4859         if (some_condition())
4860           l = &l1;
4861         else
4862           l = &l2;
4863       }
4864     }
4865   )cc";
4866   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4867 }
4868 
4869 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4870   std::string Code = R"cc(
4871     bool foo();
4872 
4873     void target() {
4874       bool c = false;
4875       while (foo() || foo()) {
4876         c = true;
4877       }
4878     }
4879   )cc";
4880   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4881 }
4882 
4883 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
4884   // Check that we can prove `b` is always false in the loop.
4885   // This test exercises the logic in `widenDistinctValues()` that preserves
4886   // information if the boolean can be proved to be either true or false in both
4887   // the previous and current iteration.
4888   std::string Code = R"cc(
4889     int return_int();
4890     void target() {
4891       bool b = return_int() == 0;
4892       if (b) return;
4893       while (true) {
4894         b;
4895         // [[p]]
4896         b = return_int() == 0;
4897         if (b) return;
4898       }
4899     }
4900   )cc";
4901   runDataflow(
4902       Code,
4903       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4904          ASTContext &ASTCtx) {
4905         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4906         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
4907         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
4908       });
4909 }
4910 
4911 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4912   std::string Code = R"cc(
4913     union Union {
4914       int A;
4915       float B;
4916     };
4917 
4918     void foo() {
4919       Union A;
4920       Union B;
4921       A = B;
4922     }
4923   )cc";
4924   // This is a crash regression test when calling the transfer function on a
4925   // `CXXThisExpr` that refers to a union.
4926   runDataflow(
4927       Code,
4928       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4929          ASTContext &) {},
4930       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4931 }
4932 
4933 TEST(TransferTest, DoesNotCrashOnNullChildren) {
4934   std::string Code = (CoroutineLibrary + R"cc(
4935     task target() noexcept {
4936       co_return;
4937     }
4938   )cc")
4939                          .str();
4940   // This is a crash regression test when calling `AdornedCFG::build` on a
4941   // statement (in this case, the `CoroutineBodyStmt`) with null children.
4942   runDataflow(
4943       Code,
4944       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4945          ASTContext &) {},
4946       LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true);
4947 }
4948 
4949 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4950   std::string Code = R"(
4951     struct A {
4952       int Foo;
4953       int Bar;
4954     };
4955 
4956     void target() {
4957       int Qux;
4958       A Baz;
4959       Baz.Foo = Qux;
4960       auto &FooRef = Baz.Foo;
4961       auto &BarRef = Baz.Bar;
4962       auto &[BoundFooRef, BoundBarRef] = Baz;
4963       // [[p]]
4964     }
4965   )";
4966   runDataflow(
4967       Code,
4968       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4969          ASTContext &ASTCtx) {
4970         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4971         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4972 
4973         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4974         ASSERT_THAT(FooRefDecl, NotNull());
4975 
4976         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4977         ASSERT_THAT(BarRefDecl, NotNull());
4978 
4979         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4980         ASSERT_THAT(QuxDecl, NotNull());
4981 
4982         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4983         ASSERT_THAT(BoundFooRefDecl, NotNull());
4984 
4985         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4986         ASSERT_THAT(BoundBarRefDecl, NotNull());
4987 
4988         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4989         ASSERT_THAT(FooRefLoc, NotNull());
4990 
4991         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4992         ASSERT_THAT(BarRefLoc, NotNull());
4993 
4994         const Value *QuxVal = Env.getValue(*QuxDecl);
4995         ASSERT_THAT(QuxVal, NotNull());
4996 
4997         const StorageLocation *BoundFooRefLoc =
4998             Env.getStorageLocation(*BoundFooRefDecl);
4999         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5000 
5001         const StorageLocation *BoundBarRefLoc =
5002             Env.getStorageLocation(*BoundBarRefDecl);
5003         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5004 
5005         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5006       });
5007 }
5008 
5009 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
5010   std::string Code = R"(
5011     struct A {
5012       int &Foo;
5013       int &Bar;
5014     };
5015 
5016     void target(A Baz) {
5017       int Qux;
5018       Baz.Foo = Qux;
5019       auto &FooRef = Baz.Foo;
5020       auto &BarRef = Baz.Bar;
5021       auto &[BoundFooRef, BoundBarRef] = Baz;
5022       // [[p]]
5023     }
5024   )";
5025   runDataflow(
5026       Code,
5027       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5028          ASTContext &ASTCtx) {
5029         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5030         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5031 
5032         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5033         ASSERT_THAT(FooRefDecl, NotNull());
5034 
5035         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5036         ASSERT_THAT(BarRefDecl, NotNull());
5037 
5038         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5039         ASSERT_THAT(QuxDecl, NotNull());
5040 
5041         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5042         ASSERT_THAT(BoundFooRefDecl, NotNull());
5043 
5044         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5045         ASSERT_THAT(BoundBarRefDecl, NotNull());
5046 
5047         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5048         ASSERT_THAT(FooRefLoc, NotNull());
5049 
5050         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5051         ASSERT_THAT(BarRefLoc, NotNull());
5052 
5053         const Value *QuxVal = Env.getValue(*QuxDecl);
5054         ASSERT_THAT(QuxVal, NotNull());
5055 
5056         const StorageLocation *BoundFooRefLoc =
5057             Env.getStorageLocation(*BoundFooRefDecl);
5058         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5059 
5060         const StorageLocation *BoundBarRefLoc =
5061             Env.getStorageLocation(*BoundBarRefDecl);
5062         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5063 
5064         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5065       });
5066 }
5067 
5068 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
5069   std::string Code = R"(
5070     struct A {
5071       int Foo;
5072       int Bar;
5073     };
5074 
5075     void target() {
5076       int Qux;
5077       A Baz;
5078       Baz.Foo = Qux;
5079       auto &FooRef = Baz.Foo;
5080       auto &BarRef = Baz.Bar;
5081       auto [BoundFoo, BoundBar] = Baz;
5082       // [[p]]
5083     }
5084   )";
5085   runDataflow(
5086       Code,
5087       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5088          ASTContext &ASTCtx) {
5089         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5090         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5091 
5092         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5093         ASSERT_THAT(FooRefDecl, NotNull());
5094 
5095         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5096         ASSERT_THAT(BarRefDecl, NotNull());
5097 
5098         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5099         ASSERT_THAT(BoundFooDecl, NotNull());
5100 
5101         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5102         ASSERT_THAT(BoundBarDecl, NotNull());
5103 
5104         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5105         ASSERT_THAT(QuxDecl, NotNull());
5106 
5107         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5108         ASSERT_THAT(FooRefLoc, NotNull());
5109 
5110         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5111         ASSERT_THAT(BarRefLoc, NotNull());
5112 
5113         const Value *QuxVal = Env.getValue(*QuxDecl);
5114         ASSERT_THAT(QuxVal, NotNull());
5115 
5116         const StorageLocation *BoundFooLoc =
5117             Env.getStorageLocation(*BoundFooDecl);
5118         EXPECT_NE(BoundFooLoc, FooRefLoc);
5119 
5120         const StorageLocation *BoundBarLoc =
5121             Env.getStorageLocation(*BoundBarDecl);
5122         EXPECT_NE(BoundBarLoc, BarRefLoc);
5123 
5124         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
5125       });
5126 }
5127 
5128 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
5129   std::string Code = R"(
5130     namespace std {
5131     using size_t = int;
5132     template <class> struct tuple_size;
5133     template <std::size_t, class> struct tuple_element;
5134     template <class...> class tuple;
5135 
5136     namespace {
5137     template <class T, T v>
5138     struct size_helper { static const T value = v; };
5139     } // namespace
5140 
5141     template <class... T>
5142     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5143 
5144     template <std::size_t I, class... T>
5145     struct tuple_element<I, tuple<T...>> {
5146       using type =  __type_pack_element<I, T...>;
5147     };
5148 
5149     template <class...> class tuple {};
5150 
5151     template <std::size_t I, class... T>
5152     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5153     } // namespace std
5154 
5155     std::tuple<bool, int> makeTuple();
5156 
5157     void target(bool B) {
5158       auto [BoundFoo, BoundBar] = makeTuple();
5159       bool Baz;
5160       // Include if-then-else to test interaction of `BindingDecl` with join.
5161       if (B) {
5162         Baz = BoundFoo;
5163         (void)BoundBar;
5164         // [[p1]]
5165       } else {
5166         Baz = BoundFoo;
5167       }
5168       (void)0;
5169       // [[p2]]
5170     }
5171   )";
5172   runDataflow(
5173       Code,
5174       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5175          ASTContext &ASTCtx) {
5176         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5177         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5178 
5179         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5180         ASSERT_THAT(BoundFooDecl, NotNull());
5181 
5182         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5183         ASSERT_THAT(BoundBarDecl, NotNull());
5184 
5185         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5186         ASSERT_THAT(BazDecl, NotNull());
5187 
5188         // BindingDecls always map to references -- either lvalue or rvalue, so
5189         // we still need to skip here.
5190         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5191         ASSERT_THAT(BoundFooValue, NotNull());
5192         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5193 
5194         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5195         ASSERT_THAT(BoundBarValue, NotNull());
5196         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5197 
5198         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
5199         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5200 
5201         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5202 
5203         // Test that `BoundFooDecl` retains the value we expect, after the join.
5204         BoundFooValue = Env2.getValue(*BoundFooDecl);
5205         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5206       });
5207 }
5208 
5209 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
5210   std::string Code = R"(
5211     namespace std {
5212     using size_t = int;
5213     template <class> struct tuple_size;
5214     template <std::size_t, class> struct tuple_element;
5215     template <class...> class tuple;
5216 
5217     namespace {
5218     template <class T, T v>
5219     struct size_helper { static const T value = v; };
5220     } // namespace
5221 
5222     template <class... T>
5223     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5224 
5225     template <std::size_t I, class... T>
5226     struct tuple_element<I, tuple<T...>> {
5227       using type =  __type_pack_element<I, T...>;
5228     };
5229 
5230     template <class...> class tuple {};
5231 
5232     template <std::size_t I, class... T>
5233     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5234     } // namespace std
5235 
5236     std::tuple<bool, int> &getTuple();
5237 
5238     void target(bool B) {
5239       auto &[BoundFoo, BoundBar] = getTuple();
5240       bool Baz;
5241       // Include if-then-else to test interaction of `BindingDecl` with join.
5242       if (B) {
5243         Baz = BoundFoo;
5244         (void)BoundBar;
5245         // [[p1]]
5246       } else {
5247         Baz = BoundFoo;
5248       }
5249       (void)0;
5250       // [[p2]]
5251     }
5252   )";
5253   runDataflow(
5254       Code,
5255       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5256          ASTContext &ASTCtx) {
5257         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5258         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5259 
5260         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5261         ASSERT_THAT(BoundFooDecl, NotNull());
5262 
5263         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5264         ASSERT_THAT(BoundBarDecl, NotNull());
5265 
5266         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5267         ASSERT_THAT(BazDecl, NotNull());
5268 
5269         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5270         ASSERT_THAT(BoundFooValue, NotNull());
5271         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5272 
5273         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5274         ASSERT_THAT(BoundBarValue, NotNull());
5275         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5276 
5277         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
5278         // works as expected. We don't test aliasing properties of the
5279         // reference, because we don't model `std::get` and so have no way to
5280         // equate separate references into the tuple.
5281         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5282 
5283         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5284 
5285         // Test that `BoundFooDecl` retains the value we expect, after the join.
5286         BoundFooValue = Env2.getValue(*BoundFooDecl);
5287         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5288       });
5289 }
5290 
5291 TEST(TransferTest, BinaryOperatorComma) {
5292   std::string Code = R"(
5293     void target(int Foo, int Bar) {
5294       int &Baz = (Foo, Bar);
5295       // [[p]]
5296     }
5297   )";
5298   runDataflow(
5299       Code,
5300       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5301          ASTContext &ASTCtx) {
5302         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5303         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5304 
5305         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5306         ASSERT_THAT(BarDecl, NotNull());
5307 
5308         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5309         ASSERT_THAT(BazDecl, NotNull());
5310 
5311         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
5312         ASSERT_THAT(BarLoc, NotNull());
5313 
5314         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
5315         EXPECT_EQ(BazLoc, BarLoc);
5316       });
5317 }
5318 
5319 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
5320   std::string Code = R"(
5321     void target(bool Foo) {
5322       if (Foo) {
5323         (void)0;
5324         // [[if_then]]
5325       } else {
5326         (void)0;
5327         // [[if_else]]
5328       }
5329     }
5330   )";
5331   runDataflow(
5332       Code,
5333       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5334          ASTContext &ASTCtx) {
5335         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
5336         const Environment &ThenEnv =
5337             getEnvironmentAtAnnotation(Results, "if_then");
5338         const Environment &ElseEnv =
5339             getEnvironmentAtAnnotation(Results, "if_else");
5340 
5341         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5342         ASSERT_THAT(FooDecl, NotNull());
5343 
5344         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
5345         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
5346 
5347         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
5348         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
5349       });
5350 }
5351 
5352 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
5353   std::string Code = R"(
5354     void target(bool Foo) {
5355       while (Foo) {
5356         (void)0;
5357         // [[loop_body]]
5358       }
5359       (void)0;
5360       // [[after_loop]]
5361     }
5362   )";
5363   runDataflow(
5364       Code,
5365       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5366          ASTContext &ASTCtx) {
5367         ASSERT_THAT(Results.keys(),
5368                     UnorderedElementsAre("loop_body", "after_loop"));
5369         const Environment &LoopBodyEnv =
5370             getEnvironmentAtAnnotation(Results, "loop_body");
5371         const Environment &AfterLoopEnv =
5372             getEnvironmentAtAnnotation(Results, "after_loop");
5373 
5374         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5375         ASSERT_THAT(FooDecl, NotNull());
5376 
5377         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
5378         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5379 
5380         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5381         EXPECT_TRUE(
5382             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5383       });
5384 }
5385 
5386 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
5387   std::string Code = R"(
5388     void target(bool Foo) {
5389       bool Bar = true;
5390       do {
5391         (void)0;
5392         // [[loop_body]]
5393         Bar = false;
5394       } while (Foo);
5395       (void)0;
5396       // [[after_loop]]
5397     }
5398   )";
5399   runDataflow(
5400       Code,
5401       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5402          ASTContext &ASTCtx) {
5403         ASSERT_THAT(Results.keys(),
5404                     UnorderedElementsAre("loop_body", "after_loop"));
5405         const Environment &LoopBodyEnv =
5406             getEnvironmentAtAnnotation(Results, "loop_body");
5407         const Environment &AfterLoopEnv =
5408             getEnvironmentAtAnnotation(Results, "after_loop");
5409         auto &A = AfterLoopEnv.arena();
5410 
5411         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5412         ASSERT_THAT(FooDecl, NotNull());
5413 
5414         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5415         ASSERT_THAT(BarDecl, NotNull());
5416 
5417         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5418         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
5419         EXPECT_TRUE(
5420             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
5421 
5422         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5423         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
5424         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
5425         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
5426       });
5427 }
5428 
5429 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
5430   std::string Code = R"(
5431     void target(bool Foo) {
5432       for (; Foo;) {
5433         (void)0;
5434         // [[loop_body]]
5435       }
5436       (void)0;
5437       // [[after_loop]]
5438     }
5439   )";
5440   runDataflow(
5441       Code,
5442       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5443          ASTContext &ASTCtx) {
5444         ASSERT_THAT(Results.keys(),
5445                     UnorderedElementsAre("loop_body", "after_loop"));
5446         const Environment &LoopBodyEnv =
5447             getEnvironmentAtAnnotation(Results, "loop_body");
5448         const Environment &AfterLoopEnv =
5449             getEnvironmentAtAnnotation(Results, "after_loop");
5450 
5451         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5452         ASSERT_THAT(FooDecl, NotNull());
5453 
5454         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5455         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5456 
5457         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5458         EXPECT_TRUE(
5459             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5460       });
5461 }
5462 
5463 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
5464   std::string Code = R"(
5465     void target(bool Foo) {
5466       for (;;) {
5467         (void)0;
5468         // [[loop_body]]
5469       }
5470     }
5471   )";
5472   runDataflow(
5473       Code,
5474       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5475          ASTContext &ASTCtx) {
5476         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
5477         const Environment &LoopBodyEnv =
5478             getEnvironmentAtAnnotation(Results, "loop_body");
5479 
5480         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5481         ASSERT_THAT(FooDecl, NotNull());
5482 
5483         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5484         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
5485       });
5486 }
5487 
5488 TEST(TransferTest, ContextSensitiveOptionDisabled) {
5489   std::string Code = R"(
5490     bool GiveBool();
5491     void SetBool(bool &Var) { Var = true; }
5492 
5493     void target() {
5494       bool Foo = GiveBool();
5495       SetBool(Foo);
5496       // [[p]]
5497     }
5498   )";
5499   runDataflow(
5500       Code,
5501       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5502          ASTContext &ASTCtx) {
5503         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5504         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5505 
5506         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5507         ASSERT_THAT(FooDecl, NotNull());
5508 
5509         auto &FooVal = getFormula(*FooDecl, Env);
5510         EXPECT_FALSE(Env.proves(FooVal));
5511         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5512       },
5513       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
5514 }
5515 
5516 TEST(TransferTest, ContextSensitiveReturnReference) {
5517   std::string Code = R"(
5518     class S {};
5519     S& target(bool b, S &s) {
5520       return s;
5521       // [[p]]
5522     }
5523   )";
5524   runDataflow(
5525       Code,
5526       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5527          ASTContext &ASTCtx) {
5528         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5529 
5530         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5531         ASSERT_THAT(SDecl, NotNull());
5532 
5533         auto *SLoc = Env.getStorageLocation(*SDecl);
5534         ASSERT_THAT(SLoc, NotNull());
5535 
5536         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
5537       },
5538       {BuiltinOptions{ContextSensitiveOptions{}}});
5539 }
5540 
5541 // This test is a regression test, based on a real crash.
5542 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
5543   std::string Code = R"(
5544     class S {};
5545     S& target(bool b, S &s) {
5546       return b ? s : s;
5547       // [[p]]
5548     }
5549   )";
5550   runDataflow(
5551       Code,
5552       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5553          ASTContext &ASTCtx) {
5554         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5555         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5556 
5557         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5558         ASSERT_THAT(SDecl, NotNull());
5559 
5560         auto *SLoc = Env.getStorageLocation(*SDecl);
5561         ASSERT_THAT(SLoc, NotNull());
5562         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
5563 
5564         auto *Loc = Env.getReturnStorageLocation();
5565         ASSERT_THAT(Loc, NotNull());
5566         EXPECT_THAT(Env.getValue(*Loc), NotNull());
5567 
5568         // TODO: We would really like to make this stronger assertion, but that
5569         // doesn't work because we don't propagate values correctly through
5570         // the conditional operator yet.
5571         // ASSERT_THAT(Loc, Eq(SLoc));
5572       },
5573       {BuiltinOptions{ContextSensitiveOptions{}}});
5574 }
5575 
5576 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5577   std::string Code = R"(
5578     class S {};
5579     S &callee(bool b, S &s1_parm, S &s2_parm) {
5580       if (b)
5581         return s1_parm;
5582       else
5583         return s2_parm;
5584     }
5585     void target(bool b) {
5586       S s1;
5587       S s2;
5588       S &return_s1 = s1;
5589       S &return_s2 = s2;
5590       S &return_dont_know = callee(b, s1, s2);
5591       // [[p]]
5592     }
5593   )";
5594   runDataflow(
5595       Code,
5596       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5597          ASTContext &ASTCtx) {
5598         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5599 
5600         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
5601         ASSERT_THAT(S1, NotNull());
5602         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
5603         ASSERT_THAT(S2, NotNull());
5604         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
5605         ASSERT_THAT(ReturnS1, NotNull());
5606         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
5607         ASSERT_THAT(ReturnS2, NotNull());
5608         const ValueDecl *ReturnDontKnow =
5609             findValueDecl(ASTCtx, "return_dont_know");
5610         ASSERT_THAT(ReturnDontKnow, NotNull());
5611 
5612         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
5613         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
5614 
5615         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
5616         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
5617 
5618         // In the case where we don't have a consistent storage location for
5619         // the return value, the framework creates a new storage location, which
5620         // should be different from the storage locations of `s1` and `s2`.
5621         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
5622         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
5623       },
5624       {BuiltinOptions{ContextSensitiveOptions{}}});
5625 }
5626 
5627 TEST(TransferTest, ContextSensitiveDepthZero) {
5628   std::string Code = R"(
5629     bool GiveBool();
5630     void SetBool(bool &Var) { Var = true; }
5631 
5632     void target() {
5633       bool Foo = GiveBool();
5634       SetBool(Foo);
5635       // [[p]]
5636     }
5637   )";
5638   runDataflow(
5639       Code,
5640       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5641          ASTContext &ASTCtx) {
5642         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5643         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5644 
5645         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5646         ASSERT_THAT(FooDecl, NotNull());
5647 
5648         auto &FooVal = getFormula(*FooDecl, Env);
5649         EXPECT_FALSE(Env.proves(FooVal));
5650         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5651       },
5652       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
5653 }
5654 
5655 TEST(TransferTest, ContextSensitiveSetTrue) {
5656   std::string Code = R"(
5657     bool GiveBool();
5658     void SetBool(bool &Var) { Var = true; }
5659 
5660     void target() {
5661       bool Foo = GiveBool();
5662       SetBool(Foo);
5663       // [[p]]
5664     }
5665   )";
5666   runDataflow(
5667       Code,
5668       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5669          ASTContext &ASTCtx) {
5670         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5671         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5672 
5673         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5674         ASSERT_THAT(FooDecl, NotNull());
5675 
5676         auto &FooVal = getFormula(*FooDecl, Env);
5677         EXPECT_TRUE(Env.proves(FooVal));
5678       },
5679       {BuiltinOptions{ContextSensitiveOptions{}}});
5680 }
5681 
5682 TEST(TransferTest, ContextSensitiveSetFalse) {
5683   std::string Code = R"(
5684     bool GiveBool();
5685     void SetBool(bool &Var) { Var = false; }
5686 
5687     void target() {
5688       bool Foo = GiveBool();
5689       SetBool(Foo);
5690       // [[p]]
5691     }
5692   )";
5693   runDataflow(
5694       Code,
5695       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5696          ASTContext &ASTCtx) {
5697         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5698         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5699 
5700         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5701         ASSERT_THAT(FooDecl, NotNull());
5702 
5703         auto &FooVal = getFormula(*FooDecl, Env);
5704         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5705       },
5706       {BuiltinOptions{ContextSensitiveOptions{}}});
5707 }
5708 
5709 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5710   std::string Code = R"(
5711     bool GiveBool();
5712     void SetBool(bool &Var, bool Val) { Var = Val; }
5713 
5714     void target() {
5715       bool Foo = GiveBool();
5716       bool Bar = GiveBool();
5717       SetBool(Foo, true);
5718       SetBool(Bar, false);
5719       // [[p]]
5720     }
5721   )";
5722   runDataflow(
5723       Code,
5724       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5725          ASTContext &ASTCtx) {
5726         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5727         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5728         auto &A = Env.arena();
5729 
5730         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5731         ASSERT_THAT(FooDecl, NotNull());
5732 
5733         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5734         ASSERT_THAT(BarDecl, NotNull());
5735 
5736         auto &FooVal = getFormula(*FooDecl, Env);
5737         EXPECT_TRUE(Env.proves(FooVal));
5738         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
5739 
5740         auto &BarVal = getFormula(*BarDecl, Env);
5741         EXPECT_FALSE(Env.proves(BarVal));
5742         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
5743       },
5744       {BuiltinOptions{ContextSensitiveOptions{}}});
5745 }
5746 
5747 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
5748   std::string Code = R"(
5749     bool GiveBool();
5750     void SetBool1(bool &Var) { Var = true; }
5751     void SetBool2(bool &Var) { SetBool1(Var); }
5752 
5753     void target() {
5754       bool Foo = GiveBool();
5755       SetBool2(Foo);
5756       // [[p]]
5757     }
5758   )";
5759   runDataflow(
5760       Code,
5761       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5762          ASTContext &ASTCtx) {
5763         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5764         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5765 
5766         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5767         ASSERT_THAT(FooDecl, NotNull());
5768 
5769         auto &FooVal = getFormula(*FooDecl, Env);
5770         EXPECT_FALSE(Env.proves(FooVal));
5771         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5772       },
5773       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5774 }
5775 
5776 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5777   std::string Code = R"(
5778     bool GiveBool();
5779     void SetBool1(bool &Var) { Var = true; }
5780     void SetBool2(bool &Var) { SetBool1(Var); }
5781 
5782     void target() {
5783       bool Foo = GiveBool();
5784       SetBool2(Foo);
5785       // [[p]]
5786     }
5787   )";
5788   runDataflow(
5789       Code,
5790       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5791          ASTContext &ASTCtx) {
5792         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5793         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5794 
5795         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5796         ASSERT_THAT(FooDecl, NotNull());
5797 
5798         auto &FooVal = getFormula(*FooDecl, Env);
5799         EXPECT_TRUE(Env.proves(FooVal));
5800       },
5801       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5802 }
5803 
5804 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5805   std::string Code = R"(
5806     bool GiveBool();
5807     void SetBool1(bool &Var) { Var = true; }
5808     void SetBool2(bool &Var) { SetBool1(Var); }
5809     void SetBool3(bool &Var) { SetBool2(Var); }
5810 
5811     void target() {
5812       bool Foo = GiveBool();
5813       SetBool3(Foo);
5814       // [[p]]
5815     }
5816   )";
5817   runDataflow(
5818       Code,
5819       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5820          ASTContext &ASTCtx) {
5821         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5822         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5823 
5824         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5825         ASSERT_THAT(FooDecl, NotNull());
5826 
5827         auto &FooVal = getFormula(*FooDecl, Env);
5828         EXPECT_FALSE(Env.proves(FooVal));
5829         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5830       },
5831       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5832 }
5833 
5834 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5835   std::string Code = R"(
5836     bool GiveBool();
5837     void SetBool1(bool &Var) { Var = true; }
5838     void SetBool2(bool &Var) { SetBool1(Var); }
5839     void SetBool3(bool &Var) { SetBool2(Var); }
5840 
5841     void target() {
5842       bool Foo = GiveBool();
5843       SetBool3(Foo);
5844       // [[p]]
5845     }
5846   )";
5847   runDataflow(
5848       Code,
5849       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5850          ASTContext &ASTCtx) {
5851         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5852         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5853 
5854         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5855         ASSERT_THAT(FooDecl, NotNull());
5856 
5857         auto &FooVal = getFormula(*FooDecl, Env);
5858         EXPECT_TRUE(Env.proves(FooVal));
5859       },
5860       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5861 }
5862 
5863 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5864   std::string Code = R"(
5865     bool Pong(bool X, bool Y);
5866 
5867     bool Ping(bool X, bool Y) {
5868       if (X) {
5869         return Y;
5870       } else {
5871         return Pong(!X, Y);
5872       }
5873     }
5874 
5875     bool Pong(bool X, bool Y) {
5876       if (Y) {
5877         return X;
5878       } else {
5879         return Ping(X, !Y);
5880       }
5881     }
5882 
5883     void target() {
5884       bool Foo = Ping(false, false);
5885       // [[p]]
5886     }
5887   )";
5888   runDataflow(
5889       Code,
5890       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5891          ASTContext &ASTCtx) {
5892         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5893         // The analysis doesn't crash...
5894         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5895 
5896         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5897         ASSERT_THAT(FooDecl, NotNull());
5898 
5899         auto &FooVal = getFormula(*FooDecl, Env);
5900         // ... but it also can't prove anything here.
5901         EXPECT_FALSE(Env.proves(FooVal));
5902         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5903       },
5904       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5905 }
5906 
5907 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5908   std::string Code = R"(
5909     void SetBools(bool &Var1, bool &Var2) {
5910       Var1 = true;
5911       Var2 = false;
5912     }
5913 
5914     void target() {
5915       bool Foo = false;
5916       bool Bar = true;
5917       SetBools(Foo, Bar);
5918       // [[p]]
5919     }
5920   )";
5921   runDataflow(
5922       Code,
5923       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5924          ASTContext &ASTCtx) {
5925         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5926         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5927 
5928         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5929         ASSERT_THAT(FooDecl, NotNull());
5930 
5931         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5932         ASSERT_THAT(BarDecl, NotNull());
5933 
5934         auto &FooVal = getFormula(*FooDecl, Env);
5935         EXPECT_TRUE(Env.proves(FooVal));
5936         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5937 
5938         auto &BarVal = getFormula(*BarDecl, Env);
5939         EXPECT_FALSE(Env.proves(BarVal));
5940         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5941       },
5942       {BuiltinOptions{ContextSensitiveOptions{}}});
5943 }
5944 
5945 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5946   std::string Code = R"(
5947     void IfCond(bool Cond, bool &Then, bool &Else) {
5948       if (Cond) {
5949         Then = true;
5950       } else {
5951         Else = true;
5952       }
5953     }
5954 
5955     void target() {
5956       bool Foo = false;
5957       bool Bar = false;
5958       bool Baz = false;
5959       IfCond(Foo, Bar, Baz);
5960       // [[p]]
5961     }
5962   )";
5963   runDataflow(
5964       Code,
5965       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5966          ASTContext &ASTCtx) {
5967         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5968         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5969 
5970         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5971         ASSERT_THAT(BarDecl, NotNull());
5972 
5973         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5974         ASSERT_THAT(BazDecl, NotNull());
5975 
5976         auto &BarVal = getFormula(*BarDecl, Env);
5977         EXPECT_FALSE(Env.proves(BarVal));
5978         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5979 
5980         auto &BazVal = getFormula(*BazDecl, Env);
5981         EXPECT_TRUE(Env.proves(BazVal));
5982         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5983       },
5984       {BuiltinOptions{ContextSensitiveOptions{}}});
5985 }
5986 
5987 TEST(TransferTest, ContextSensitiveReturnVoid) {
5988   std::string Code = R"(
5989     void Noop() { return; }
5990 
5991     void target() {
5992       Noop();
5993       // [[p]]
5994     }
5995   )";
5996   runDataflow(
5997       Code,
5998       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5999          ASTContext &ASTCtx) {
6000         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6001         // This just tests that the analysis doesn't crash.
6002       },
6003       {BuiltinOptions{ContextSensitiveOptions{}}});
6004 }
6005 
6006 TEST(TransferTest, ContextSensitiveReturnTrue) {
6007   std::string Code = R"(
6008     bool GiveBool() { return true; }
6009 
6010     void target() {
6011       bool Foo = GiveBool();
6012       // [[p]]
6013     }
6014   )";
6015   runDataflow(
6016       Code,
6017       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6018          ASTContext &ASTCtx) {
6019         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6020         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6021 
6022         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6023         ASSERT_THAT(FooDecl, NotNull());
6024 
6025         auto &FooVal = getFormula(*FooDecl, Env);
6026         EXPECT_TRUE(Env.proves(FooVal));
6027       },
6028       {BuiltinOptions{ContextSensitiveOptions{}}});
6029 }
6030 
6031 TEST(TransferTest, ContextSensitiveReturnFalse) {
6032   std::string Code = R"(
6033     bool GiveBool() { return false; }
6034 
6035     void target() {
6036       bool Foo = GiveBool();
6037       // [[p]]
6038     }
6039   )";
6040   runDataflow(
6041       Code,
6042       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6043          ASTContext &ASTCtx) {
6044         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6045         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6046 
6047         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6048         ASSERT_THAT(FooDecl, NotNull());
6049 
6050         auto &FooVal = getFormula(*FooDecl, Env);
6051         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
6052       },
6053       {BuiltinOptions{ContextSensitiveOptions{}}});
6054 }
6055 
6056 TEST(TransferTest, ContextSensitiveReturnArg) {
6057   std::string Code = R"(
6058     bool GiveBool();
6059     bool GiveBack(bool Arg) { return Arg; }
6060 
6061     void target() {
6062       bool Foo = GiveBool();
6063       bool Bar = GiveBack(Foo);
6064       bool Baz = Foo == Bar;
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         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6074 
6075         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
6076         ASSERT_THAT(BazDecl, NotNull());
6077 
6078         auto &BazVal = getFormula(*BazDecl, Env);
6079         EXPECT_TRUE(Env.proves(BazVal));
6080       },
6081       {BuiltinOptions{ContextSensitiveOptions{}}});
6082 }
6083 
6084 TEST(TransferTest, ContextSensitiveReturnInt) {
6085   std::string Code = R"(
6086     int identity(int x) { return x; }
6087 
6088     void target() {
6089       int y = identity(42);
6090       // [[p]]
6091     }
6092   )";
6093   runDataflow(
6094       Code,
6095       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6096          ASTContext &ASTCtx) {
6097         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6098         // This just tests that the analysis doesn't crash.
6099       },
6100       {BuiltinOptions{ContextSensitiveOptions{}}});
6101 }
6102 
6103 TEST(TransferTest, ContextSensitiveReturnRecord) {
6104   std::string Code = R"(
6105     struct S {
6106       bool B;
6107     };
6108 
6109     S makeS(bool BVal) { return {BVal}; }
6110 
6111     void target() {
6112       S FalseS = makeS(false);
6113       S TrueS = makeS(true);
6114       // [[p]]
6115     }
6116   )";
6117   runDataflow(
6118       Code,
6119       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6120          ASTContext &ASTCtx) {
6121         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6122 
6123         auto &FalseSLoc =
6124             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "FalseS");
6125         auto &TrueSLoc =
6126             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "TrueS");
6127 
6128         EXPECT_EQ(getFieldValue(&FalseSLoc, "B", ASTCtx, Env),
6129                   &Env.getBoolLiteralValue(false));
6130         EXPECT_EQ(getFieldValue(&TrueSLoc, "B", ASTCtx, Env),
6131                   &Env.getBoolLiteralValue(true));
6132       },
6133       {BuiltinOptions{ContextSensitiveOptions{}}});
6134 }
6135 
6136 TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {
6137   std::string Code = R"(
6138     struct S {
6139       S() { self = this; }
6140       S *self;
6141     };
6142 
6143     S makeS() {
6144       // RVO guarantees that this will be constructed directly into `MyS`.
6145       return S();
6146     }
6147 
6148     void target() {
6149       S MyS = makeS();
6150       // [[p]]
6151     }
6152   )";
6153   runDataflow(
6154       Code,
6155       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6156          ASTContext &ASTCtx) {
6157         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6158 
6159         auto &MySLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MyS");
6160 
6161         auto *SelfVal =
6162             cast<PointerValue>(getFieldValue(&MySLoc, "self", ASTCtx, Env));
6163         EXPECT_EQ(&SelfVal->getPointeeLoc(), &MySLoc);
6164       },
6165       {BuiltinOptions{ContextSensitiveOptions{}}});
6166 }
6167 
6168 TEST(TransferTest, ContextSensitiveMethodLiteral) {
6169   std::string Code = R"(
6170     class MyClass {
6171     public:
6172       bool giveBool() { return true; }
6173     };
6174 
6175     void target() {
6176       MyClass MyObj;
6177       bool Foo = MyObj.giveBool();
6178       // [[p]]
6179     }
6180   )";
6181   runDataflow(
6182       Code,
6183       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6184          ASTContext &ASTCtx) {
6185         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6186         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6187 
6188         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6189         ASSERT_THAT(FooDecl, NotNull());
6190 
6191         auto &FooVal = getFormula(*FooDecl, Env);
6192         EXPECT_TRUE(Env.proves(FooVal));
6193       },
6194       {BuiltinOptions{ContextSensitiveOptions{}}});
6195 }
6196 
6197 TEST(TransferTest, ContextSensitiveMethodGetter) {
6198   std::string Code = R"(
6199     class MyClass {
6200     public:
6201       bool getField() { return Field; }
6202 
6203       bool Field;
6204     };
6205 
6206     void target() {
6207       MyClass MyObj;
6208       MyObj.Field = true;
6209       bool Foo = MyObj.getField();
6210       // [[p]]
6211     }
6212   )";
6213   runDataflow(
6214       Code,
6215       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6216          ASTContext &ASTCtx) {
6217         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6218         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6219 
6220         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6221         ASSERT_THAT(FooDecl, NotNull());
6222 
6223         auto &FooVal = getFormula(*FooDecl, Env);
6224         EXPECT_TRUE(Env.proves(FooVal));
6225       },
6226       {BuiltinOptions{ContextSensitiveOptions{}}});
6227 }
6228 
6229 TEST(TransferTest, ContextSensitiveMethodSetter) {
6230   std::string Code = R"(
6231     class MyClass {
6232     public:
6233       void setField(bool Val) { Field = Val; }
6234 
6235       bool Field;
6236     };
6237 
6238     void target() {
6239       MyClass MyObj;
6240       MyObj.setField(true);
6241       bool Foo = MyObj.Field;
6242       // [[p]]
6243     }
6244   )";
6245   runDataflow(
6246       Code,
6247       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6248          ASTContext &ASTCtx) {
6249         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6250         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6251 
6252         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6253         ASSERT_THAT(FooDecl, NotNull());
6254 
6255         auto &FooVal = getFormula(*FooDecl, Env);
6256         EXPECT_TRUE(Env.proves(FooVal));
6257       },
6258       {BuiltinOptions{ContextSensitiveOptions{}}});
6259 }
6260 
6261 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
6262   std::string Code = R"(
6263     class MyClass {
6264     public:
6265       bool getField() { return Field; }
6266       void setField(bool Val) { Field = Val; }
6267 
6268     private:
6269       bool Field;
6270     };
6271 
6272     void target() {
6273       MyClass MyObj;
6274       MyObj.setField(true);
6275       bool Foo = MyObj.getField();
6276       // [[p]]
6277     }
6278   )";
6279   runDataflow(
6280       Code,
6281       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6282          ASTContext &ASTCtx) {
6283         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6284         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6285 
6286         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6287         ASSERT_THAT(FooDecl, NotNull());
6288 
6289         auto &FooVal = getFormula(*FooDecl, Env);
6290         EXPECT_TRUE(Env.proves(FooVal));
6291       },
6292       {BuiltinOptions{ContextSensitiveOptions{}}});
6293 }
6294 
6295 
6296 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
6297   std::string Code = R"(
6298     class MyClass {
6299     public:
6300       void Inner() { MyField = true; }
6301       void Outer() { Inner(); }
6302 
6303       bool MyField;
6304     };
6305 
6306     void target() {
6307       MyClass MyObj;
6308       MyObj.Outer();
6309       bool Foo = MyObj.MyField;
6310       // [[p]]
6311     }
6312   )";
6313   runDataflow(
6314       Code,
6315       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6316          ASTContext &ASTCtx) {
6317         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6318         ;
6319         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6320 
6321         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6322         ASSERT_THAT(FooDecl, NotNull());
6323 
6324         auto &FooVal = getFormula(*FooDecl, Env);
6325         EXPECT_TRUE(Env.proves(FooVal));
6326       },
6327       {BuiltinOptions{ContextSensitiveOptions{}}});
6328 }
6329 
6330 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
6331   std::string Code = R"(
6332     class MyClass {
6333     public:
6334       bool Inner() { return MyField; }
6335       bool Outer() { return Inner(); }
6336 
6337       bool MyField;
6338     };
6339 
6340     void target() {
6341       MyClass MyObj;
6342       MyObj.MyField = true;
6343       bool Foo = MyObj.Outer();
6344       // [[p]]
6345     }
6346   )";
6347   runDataflow(
6348       Code,
6349       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6350          ASTContext &ASTCtx) {
6351         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6352         ;
6353         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6354 
6355         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6356         ASSERT_THAT(FooDecl, NotNull());
6357 
6358         auto &FooVal = getFormula(*FooDecl, Env);
6359         EXPECT_TRUE(Env.proves(FooVal));
6360       },
6361       {BuiltinOptions{ContextSensitiveOptions{}}});
6362 }
6363 
6364 TEST(TransferTest, ContextSensitiveConstructorBody) {
6365   std::string Code = R"(
6366     class MyClass {
6367     public:
6368       MyClass() { MyField = true; }
6369 
6370       bool MyField;
6371     };
6372 
6373     void target() {
6374       MyClass MyObj;
6375       bool Foo = MyObj.MyField;
6376       // [[p]]
6377     }
6378   )";
6379   runDataflow(
6380       Code,
6381       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6382          ASTContext &ASTCtx) {
6383         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6384         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6385 
6386         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6387         ASSERT_THAT(FooDecl, NotNull());
6388 
6389         auto &FooVal = getFormula(*FooDecl, Env);
6390         EXPECT_TRUE(Env.proves(FooVal));
6391       },
6392       {BuiltinOptions{ContextSensitiveOptions{}}});
6393 }
6394 
6395 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
6396   std::string Code = R"(
6397     class MyClass {
6398     public:
6399       MyClass() : MyField(true) {}
6400 
6401       bool MyField;
6402     };
6403 
6404     void target() {
6405       MyClass MyObj;
6406       bool Foo = MyObj.MyField;
6407       // [[p]]
6408     }
6409   )";
6410   runDataflow(
6411       Code,
6412       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6413          ASTContext &ASTCtx) {
6414         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6415         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6416 
6417         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6418         ASSERT_THAT(FooDecl, NotNull());
6419 
6420         auto &FooVal = getFormula(*FooDecl, Env);
6421         EXPECT_TRUE(Env.proves(FooVal));
6422       },
6423       {BuiltinOptions{ContextSensitiveOptions{}}});
6424 }
6425 
6426 TEST(TransferTest, ContextSensitiveConstructorDefault) {
6427   std::string Code = R"(
6428     class MyClass {
6429     public:
6430       MyClass() = default;
6431 
6432       bool MyField = true;
6433     };
6434 
6435     void target() {
6436       MyClass MyObj;
6437       bool Foo = MyObj.MyField;
6438       // [[p]]
6439     }
6440   )";
6441   runDataflow(
6442       Code,
6443       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6444          ASTContext &ASTCtx) {
6445         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6446         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6447 
6448         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6449         ASSERT_THAT(FooDecl, NotNull());
6450 
6451         auto &FooVal = getFormula(*FooDecl, Env);
6452         EXPECT_TRUE(Env.proves(FooVal));
6453       },
6454       {BuiltinOptions{ContextSensitiveOptions{}}});
6455 }
6456 
6457 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
6458   // Test that the `this` pointer seen in the constructor has the same value
6459   // as the address of the variable the object is constructed into.
6460   std::string Code = R"(
6461     class MyClass {
6462     public:
6463       MyClass() : Self(this) {}
6464       MyClass *Self;
6465     };
6466 
6467     void target() {
6468       MyClass MyObj;
6469       MyClass *SelfPtr = MyObj.Self;
6470       // [[p]]
6471     }
6472   )";
6473   runDataflow(
6474       Code,
6475       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6476          ASTContext &ASTCtx) {
6477         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6478 
6479         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
6480         ASSERT_THAT(MyObjDecl, NotNull());
6481 
6482         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
6483         ASSERT_THAT(SelfDecl, NotNull());
6484 
6485         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6486         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
6487         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
6488       },
6489       {BuiltinOptions{ContextSensitiveOptions{}}});
6490 }
6491 
6492 TEST(TransferTest, UnnamedBitfieldInitializer) {
6493   std::string Code = R"(
6494     struct B {};
6495     struct A {
6496       unsigned a;
6497       unsigned : 4;
6498       unsigned c;
6499       B b;
6500     };
6501     void target() {
6502       A a = {};
6503       A test = a;
6504       (void)test.c;
6505     }
6506   )";
6507   runDataflow(
6508       Code,
6509       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6510          ASTContext &ASTCtx) {
6511         // This doesn't need a body because this test was crashing the framework
6512         // before handling correctly Unnamed bitfields in `InitListExpr`.
6513       });
6514 }
6515 
6516 // Repro for a crash that used to occur with chained short-circuiting logical
6517 // operators.
6518 TEST(TransferTest, ChainedLogicalOps) {
6519   std::string Code = R"(
6520     bool target() {
6521       bool b = true || false || false || false;
6522       // [[p]]
6523       return b;
6524     }
6525   )";
6526   runDataflow(
6527       Code,
6528       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6529          ASTContext &ASTCtx) {
6530         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6531         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6532         EXPECT_TRUE(Env.proves(B));
6533       });
6534 }
6535 
6536 // Repro for a crash that used to occur when we call a `noreturn` function
6537 // within one of the operands of a `&&` or `||` operator.
6538 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
6539   std::string Code = R"(
6540     __attribute__((noreturn)) int doesnt_return();
6541     bool some_condition();
6542     void target(bool b1, bool b2) {
6543       // Neither of these should crash. In addition, if we don't terminate the
6544       // program, we know that the operators need to trigger the short-circuit
6545       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
6546       // will be true.
6547       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
6548       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
6549 
6550       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
6551       // entire expression unreachable. So we know that in both of the following
6552       // cases, if `target()` terminates, the `else` branch was taken.
6553       bool NoreturnOnLhsMakesAndUnreachable = false;
6554       if (some_condition())
6555          doesnt_return() > 0 && some_condition();
6556       else
6557          NoreturnOnLhsMakesAndUnreachable = true;
6558 
6559       bool NoreturnOnLhsMakesOrUnreachable = false;
6560       if (some_condition())
6561          doesnt_return() > 0 || some_condition();
6562       else
6563          NoreturnOnLhsMakesOrUnreachable = true;
6564 
6565       // [[p]]
6566     }
6567   )";
6568   runDataflow(
6569       Code,
6570       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6571          ASTContext &ASTCtx) {
6572         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6573         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6574         auto &A = Env.arena();
6575 
6576         // Check that [[p]] is reachable with a non-false flow condition.
6577         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
6578 
6579         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
6580         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
6581 
6582         auto &NoreturnOnRhsOfAnd =
6583             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
6584         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
6585 
6586         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
6587         EXPECT_TRUE(Env.proves(B2));
6588 
6589         auto &NoreturnOnRhsOfOr =
6590             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
6591                 .formula();
6592         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
6593 
6594         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
6595             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
6596         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
6597 
6598         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
6599             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
6600         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
6601       });
6602 }
6603 
6604 TEST(TransferTest, NewExpressions) {
6605   std::string Code = R"(
6606     void target() {
6607       int *p = new int(42);
6608       // [[after_new]]
6609     }
6610   )";
6611   runDataflow(
6612       Code,
6613       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6614          ASTContext &ASTCtx) {
6615         const Environment &Env =
6616             getEnvironmentAtAnnotation(Results, "after_new");
6617 
6618         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6619 
6620         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
6621       });
6622 }
6623 
6624 TEST(TransferTest, NewExpressions_Structs) {
6625   std::string Code = R"(
6626     struct Inner {
6627       int InnerField;
6628     };
6629 
6630     struct Outer {
6631       Inner OuterField;
6632     };
6633 
6634     void target() {
6635       Outer *p = new Outer;
6636       // Access the fields to make sure the analysis actually generates children
6637       // for them in the `RecordStorageLocation` and `RecordValue`.
6638       p->OuterField.InnerField;
6639       // [[after_new]]
6640     }
6641   )";
6642   runDataflow(
6643       Code,
6644       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6645          ASTContext &ASTCtx) {
6646         const Environment &Env =
6647             getEnvironmentAtAnnotation(Results, "after_new");
6648 
6649         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
6650         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
6651 
6652         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6653 
6654         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
6655         auto &OuterFieldLoc =
6656             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
6657         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
6658 
6659         // Values for the struct and all fields exist after the new.
6660         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
6661         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
6662         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
6663       });
6664 }
6665 
6666 TEST(TransferTest, FunctionToPointerDecayHasValue) {
6667   std::string Code = R"(
6668     struct A { static void static_member_func(); };
6669     void target() {
6670       // To check that we're treating function-to-pointer decay correctly,
6671       // create two pointers, then verify they refer to the same storage
6672       // location.
6673       // We need to do the test this way because even if an initializer (in this
6674       // case, the function-to-pointer decay) does not create a value, we still
6675       // create a value for the variable.
6676       void (*non_member_p1)() = target;
6677       void (*non_member_p2)() = target;
6678 
6679       // Do the same thing but for a static member function.
6680       void (*member_p1)() = A::static_member_func;
6681       void (*member_p2)() = A::static_member_func;
6682       // [[p]]
6683     }
6684   )";
6685   runDataflow(
6686       Code,
6687       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6688          ASTContext &ASTCtx) {
6689         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6690 
6691         auto &NonMemberP1 =
6692             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
6693         auto &NonMemberP2 =
6694             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
6695         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
6696 
6697         auto &MemberP1 =
6698             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
6699         auto &MemberP2 =
6700             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
6701         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
6702       });
6703 }
6704 
6705 // Check that a builtin function is not associated with a value. (It's only
6706 // possible to call builtin functions directly, not take their address.)
6707 TEST(TransferTest, BuiltinFunctionModeled) {
6708   std::string Code = R"(
6709     void target() {
6710       __builtin_expect(0, 0);
6711       // [[p]]
6712     }
6713   )";
6714   runDataflow(
6715       Code,
6716       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6717          ASTContext &ASTCtx) {
6718         using ast_matchers::selectFirst;
6719         using ast_matchers::match;
6720         using ast_matchers::traverse;
6721         using ast_matchers::implicitCastExpr;
6722         using ast_matchers::hasCastKind;
6723 
6724         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6725 
6726         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
6727             "implicit_cast",
6728             match(traverse(TK_AsIs,
6729                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
6730                                .bind("implicit_cast")),
6731                   ASTCtx));
6732 
6733         ASSERT_THAT(ImplicitCast, NotNull());
6734         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
6735       });
6736 }
6737 
6738 // Check that a callee of a member operator call is modeled as a `PointerValue`.
6739 // Member operator calls are unusual in that their callee is a pointer that
6740 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
6741 // member functions, the callee is a `MemberExpr` (which does not have pointer
6742 // type).
6743 // We want to make sure that we produce a pointer value for the callee in this
6744 // specific scenario and that its storage location is durable (for convergence).
6745 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
6746   std::string Code = R"(
6747     struct S {
6748       bool operator!=(S s);
6749     };
6750     void target() {
6751       S s;
6752       (void)(s != s);
6753       (void)(s != s);
6754       // [[p]]
6755     }
6756   )";
6757   runDataflow(
6758       Code,
6759       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6760          ASTContext &ASTCtx) {
6761         using ast_matchers::selectFirst;
6762         using ast_matchers::match;
6763         using ast_matchers::traverse;
6764         using ast_matchers::cxxOperatorCallExpr;
6765 
6766         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6767 
6768         auto Matches = match(
6769             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
6770 
6771         ASSERT_EQ(Matches.size(), 2UL);
6772 
6773         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
6774         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
6775 
6776         ASSERT_THAT(Call1, NotNull());
6777         ASSERT_THAT(Call2, NotNull());
6778 
6779         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
6780                   CK_FunctionToPointerDecay);
6781         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
6782                   CK_FunctionToPointerDecay);
6783 
6784         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
6785         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
6786 
6787         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
6788       });
6789 }
6790 
6791 // Check that fields of anonymous records are modeled.
6792 TEST(TransferTest, AnonymousStruct) {
6793   std::string Code = R"(
6794     struct S {
6795       struct {
6796         bool b;
6797       };
6798     };
6799     void target() {
6800       S s;
6801       s.b = true;
6802       // [[p]]
6803     }
6804   )";
6805   runDataflow(
6806       Code,
6807       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6808          ASTContext &ASTCtx) {
6809         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6810         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
6811         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6812         const IndirectFieldDecl *IndirectField =
6813             findIndirectFieldDecl(ASTCtx, "b");
6814 
6815         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
6816         auto &AnonStruct = *cast<RecordStorageLocation>(
6817             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
6818 
6819         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6820         ASSERT_TRUE(Env.proves(B->formula()));
6821       });
6822 }
6823 
6824 TEST(TransferTest, AnonymousStructWithInitializer) {
6825   std::string Code = R"(
6826     struct target {
6827       target() {
6828         (void)0;
6829         // [[p]]
6830       }
6831       struct {
6832         bool b = true;
6833       };
6834     };
6835   )";
6836   runDataflow(
6837       Code,
6838       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6839          ASTContext &ASTCtx) {
6840         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6841         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6842         const IndirectFieldDecl *IndirectField =
6843             findIndirectFieldDecl(ASTCtx, "b");
6844 
6845         auto *ThisLoc =
6846             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6847         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6848             *cast<ValueDecl>(IndirectField->chain().front())));
6849 
6850         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6851         ASSERT_TRUE(Env.proves(B->formula()));
6852       });
6853 }
6854 
6855 TEST(TransferTest, AnonymousStructWithReferenceField) {
6856   std::string Code = R"(
6857     int global_i = 0;
6858     struct target {
6859       target() {
6860         (void)0;
6861         // [[p]]
6862       }
6863       struct {
6864         int &i = global_i;
6865       };
6866     };
6867   )";
6868   runDataflow(
6869       Code,
6870       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6871          ASTContext &ASTCtx) {
6872         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6873         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6874         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6875         const IndirectFieldDecl *IndirectField =
6876             findIndirectFieldDecl(ASTCtx, "i");
6877 
6878         auto *ThisLoc =
6879             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6880         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6881             *cast<ValueDecl>(IndirectField->chain().front())));
6882 
6883         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6884                   Env.getStorageLocation(*GlobalIDecl));
6885       });
6886 }
6887 
6888 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6889   // This is a crash repro.
6890   // `false` block may not have been processed when we try to evaluate the `||`
6891   // after visiting `true`, because it is not necessary (and therefore the edge
6892   // is marked unreachable). Trying to get the analysis state via
6893   // `getEnvironment` for the subexpression still should not crash.
6894   std::string Code = R"(
6895     int target(int i) {
6896       if ((i < 0 && true) || false) {
6897         return 0;
6898       }
6899       return 0;
6900     }
6901   )";
6902   runDataflow(
6903       Code,
6904       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6905          ASTContext &ASTCtx) {});
6906 }
6907 
6908 TEST(TransferTest, LambdaCaptureByCopy) {
6909   std::string Code = R"(
6910     void target(int Foo, int Bar) {
6911       [Foo]() {
6912         (void)0;
6913         // [[p]]
6914       }();
6915     }
6916   )";
6917   runDataflowOnLambda(
6918       Code,
6919       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6920          ASTContext &ASTCtx) {
6921         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6922         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6923 
6924         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6925         ASSERT_THAT(FooDecl, NotNull());
6926 
6927         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6928         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6929 
6930         const Value *FooVal = Env.getValue(*FooLoc);
6931         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6932 
6933         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6934         ASSERT_THAT(BarDecl, NotNull());
6935 
6936         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6937         EXPECT_THAT(BarLoc, IsNull());
6938       });
6939 }
6940 
6941 TEST(TransferTest, LambdaCaptureByReference) {
6942   std::string Code = R"(
6943     void target(int Foo, int Bar) {
6944       [&Foo]() {
6945         (void)0;
6946         // [[p]]
6947       }();
6948     }
6949   )";
6950   runDataflowOnLambda(
6951       Code,
6952       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6953          ASTContext &ASTCtx) {
6954         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6955         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6956 
6957         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6958         ASSERT_THAT(FooDecl, NotNull());
6959 
6960         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6961         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6962 
6963         const Value *FooVal = Env.getValue(*FooLoc);
6964         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6965 
6966         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6967         ASSERT_THAT(BarDecl, NotNull());
6968 
6969         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6970         EXPECT_THAT(BarLoc, IsNull());
6971       });
6972 }
6973 
6974 TEST(TransferTest, LambdaCaptureWithInitializer) {
6975   std::string Code = R"(
6976     void target(int Bar) {
6977       [Foo=Bar]() {
6978         (void)0;
6979         // [[p]]
6980       }();
6981     }
6982   )";
6983   runDataflowOnLambda(
6984       Code,
6985       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6986          ASTContext &ASTCtx) {
6987         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6988         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6989 
6990         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6991         ASSERT_THAT(FooDecl, NotNull());
6992 
6993         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6994         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6995 
6996         const Value *FooVal = Env.getValue(*FooLoc);
6997         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6998 
6999         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7000         ASSERT_THAT(BarDecl, NotNull());
7001 
7002         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7003         EXPECT_THAT(BarLoc, IsNull());
7004       });
7005 }
7006 
7007 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
7008   std::string Code = R"(
7009     void target(int Foo, int Bar) {
7010       [=]() {
7011         Foo;
7012         // [[p]]
7013       }();
7014     }
7015   )";
7016   runDataflowOnLambda(
7017       Code,
7018       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7019          ASTContext &ASTCtx) {
7020         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7021         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7022 
7023         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7024         ASSERT_THAT(FooDecl, NotNull());
7025 
7026         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7027         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7028 
7029         const Value *FooVal = Env.getValue(*FooLoc);
7030         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7031 
7032         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7033         ASSERT_THAT(BarDecl, NotNull());
7034 
7035         // There is no storage location for `Bar` because it isn't used in the
7036         // body of the lambda.
7037         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7038         EXPECT_THAT(BarLoc, IsNull());
7039       });
7040 }
7041 
7042 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
7043   std::string Code = R"(
7044     void target(int Foo, int Bar) {
7045       [&]() {
7046         Foo;
7047         // [[p]]
7048       }();
7049     }
7050   )";
7051   runDataflowOnLambda(
7052       Code,
7053       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7054          ASTContext &ASTCtx) {
7055         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7056         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7057 
7058         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7059         ASSERT_THAT(FooDecl, NotNull());
7060 
7061         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7062         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7063 
7064         const Value *FooVal = Env.getValue(*FooLoc);
7065         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7066 
7067         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7068         ASSERT_THAT(BarDecl, NotNull());
7069 
7070         // There is no storage location for `Bar` because it isn't used in the
7071         // body of the lambda.
7072         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7073         EXPECT_THAT(BarLoc, IsNull());
7074       });
7075 }
7076 
7077 TEST(TransferTest, LambdaCaptureThis) {
7078   std::string Code = R"(
7079     struct Bar {
7080       int Foo;
7081 
7082       void target() {
7083         [this]() {
7084           Foo;
7085           // [[p]]
7086         }();
7087       }
7088     };
7089   )";
7090   runDataflowOnLambda(
7091       Code,
7092       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7093          ASTContext &ASTCtx) {
7094         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7095         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7096 
7097         const RecordStorageLocation *ThisPointeeLoc =
7098             Env.getThisPointeeStorageLocation();
7099         ASSERT_THAT(ThisPointeeLoc, NotNull());
7100 
7101         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7102         ASSERT_THAT(FooDecl, NotNull());
7103 
7104         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
7105         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7106 
7107         const Value *FooVal = Env.getValue(*FooLoc);
7108         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7109       });
7110 }
7111 
7112 // This test verifies correct modeling of a relational dependency that goes
7113 // through unmodeled functions (the simple `cond()` in this case).
7114 TEST(TransferTest, ConditionalRelation) {
7115   std::string Code = R"(
7116     bool cond();
7117     void target() {
7118        bool a = true;
7119        bool b = true;
7120        if (cond()) {
7121          a = false;
7122          if (cond()) {
7123            b = false;
7124          }
7125        }
7126        (void)0;
7127        // [[p]]
7128     }
7129  )";
7130   runDataflow(
7131       Code,
7132       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7133          ASTContext &ASTCtx) {
7134         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7135         auto &A = Env.arena();
7136         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
7137         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
7138 
7139         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
7140       });
7141 }
7142 
7143 } // namespace
7144