xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision b851c7f1fc4fd83ea84d565bbdc30fd0d356788c)
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 // Check that the `std::strong_ordering` object returned by builtin `<=>` has a
3102 // correctly modeled result object location.
3103 TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {
3104   std::string Code = R"(
3105     namespace std {
3106       // This is the minimal definition required to get
3107       // `Sema::CheckComparisonCategoryType()` to accept this fake.
3108       struct strong_ordering {
3109         enum class ordering { less, equal, greater };
3110         ordering o;
3111         static const strong_ordering less;
3112         static const strong_ordering equivalent;
3113         static const strong_ordering equal;
3114         static const strong_ordering greater;
3115       };
3116 
3117       inline constexpr strong_ordering strong_ordering::less =
3118         { strong_ordering::ordering::less };
3119       inline constexpr strong_ordering strong_ordering::equal =
3120         { strong_ordering::ordering::equal };
3121       inline constexpr strong_ordering strong_ordering::equivalent =
3122         { strong_ordering::ordering::equal };
3123       inline constexpr strong_ordering strong_ordering::greater =
3124         { strong_ordering::ordering::greater };
3125     }
3126     void target(int i, int j) {
3127       auto ordering = i <=> j;
3128       // [[p]]
3129     }
3130   )";
3131   using ast_matchers::binaryOperator;
3132   using ast_matchers::hasOperatorName;
3133   using ast_matchers::match;
3134   using ast_matchers::selectFirst;
3135   using ast_matchers::traverse;
3136   runDataflow(
3137       Code,
3138       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3139          ASTContext &ASTCtx) {
3140         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3141 
3142         auto *Spaceship = selectFirst<BinaryOperator>(
3143             "op",
3144             match(binaryOperator(hasOperatorName("<=>")).bind("op"), ASTCtx));
3145 
3146         EXPECT_EQ(
3147             &Env.getResultObjectLocation(*Spaceship),
3148             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "ordering"));
3149       },
3150       LangStandard::lang_cxx20);
3151 }
3152 
3153 TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {
3154   std::string Code = R"(
3155     namespace std {
3156     template <typename T>
3157     struct initializer_list {};
3158     } // namespace std
3159 
3160     void target() {
3161       std::initializer_list<int> list = {1};
3162       // [[p]]
3163     }
3164   )";
3165 
3166   using ast_matchers::cxxStdInitializerListExpr;
3167   using ast_matchers::match;
3168   using ast_matchers::selectFirst;
3169   runDataflow(
3170       Code,
3171       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3172          ASTContext &ASTCtx) {
3173         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3174 
3175         auto *StdInitList = selectFirst<CXXStdInitializerListExpr>(
3176             "std_init_list",
3177             match(cxxStdInitializerListExpr().bind("std_init_list"), ASTCtx));
3178         ASSERT_NE(StdInitList, nullptr);
3179 
3180         EXPECT_EQ(&Env.getResultObjectLocation(*StdInitList),
3181                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "list"));
3182       });
3183 }
3184 
3185 TEST(TransferTest, ResultObjectLocationForStmtExpr) {
3186   std::string Code = R"(
3187     struct S {};
3188     void target() {
3189       S s = ({ S(); });
3190       // [[p]]
3191     }
3192   )";
3193   using ast_matchers::cxxConstructExpr;
3194   using ast_matchers::match;
3195   using ast_matchers::selectFirst;
3196   using ast_matchers::traverse;
3197   runDataflow(
3198       Code,
3199       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3200          ASTContext &ASTCtx) {
3201         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3202 
3203         auto *Construct = selectFirst<CXXConstructExpr>(
3204             "construct", match(cxxConstructExpr().bind("construct"), ASTCtx));
3205 
3206         EXPECT_EQ(&Env.getResultObjectLocation(*Construct),
3207                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3208       });
3209 }
3210 
3211 TEST(TransferTest, ResultObjectLocationPropagatesThroughConditionalOperator) {
3212   std::string Code = R"(
3213     struct A {
3214       A(int);
3215     };
3216 
3217     void target(bool b) {
3218       A a = b ? A(0) : A(1);
3219       (void)0; // [[p]]
3220     }
3221   )";
3222   using ast_matchers::cxxConstructExpr;
3223   using ast_matchers::equals;
3224   using ast_matchers::hasArgument;
3225   using ast_matchers::integerLiteral;
3226   using ast_matchers::match;
3227   using ast_matchers::selectFirst;
3228   using ast_matchers::traverse;
3229   runDataflow(
3230       Code,
3231       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3232          ASTContext &ASTCtx) {
3233         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3234 
3235         auto *ConstructExpr0 = selectFirst<CXXConstructExpr>(
3236             "construct",
3237             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(0))))
3238                       .bind("construct"),
3239                   ASTCtx));
3240         auto *ConstructExpr1 = selectFirst<CXXConstructExpr>(
3241             "construct",
3242             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(1))))
3243                       .bind("construct"),
3244                   ASTCtx));
3245 
3246         auto &ALoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "a");
3247         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr0), &ALoc);
3248         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr1), &ALoc);
3249       });
3250 }
3251 
3252 TEST(TransferTest, StaticCast) {
3253   std::string Code = R"(
3254     void target(int Foo) {
3255       int Bar = static_cast<int>(Foo);
3256       // [[p]]
3257     }
3258   )";
3259   runDataflow(
3260       Code,
3261       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3262          ASTContext &ASTCtx) {
3263         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3264         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3265 
3266         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3267         ASSERT_THAT(FooDecl, NotNull());
3268 
3269         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3270         ASSERT_THAT(BarDecl, NotNull());
3271 
3272         const auto *FooVal = Env.getValue(*FooDecl);
3273         const auto *BarVal = Env.getValue(*BarDecl);
3274         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3275         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3276         EXPECT_EQ(FooVal, BarVal);
3277       });
3278 }
3279 
3280 TEST(TransferTest, IntegralCast) {
3281   std::string Code = R"(
3282     void target(int Foo) {
3283       long Bar = Foo;
3284       // [[p]]
3285     }
3286   )";
3287   runDataflow(
3288       Code,
3289       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3290          ASTContext &ASTCtx) {
3291         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3292         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3293 
3294         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3295         ASSERT_THAT(FooDecl, NotNull());
3296 
3297         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3298         ASSERT_THAT(BarDecl, NotNull());
3299 
3300         const auto *FooVal = Env.getValue(*FooDecl);
3301         const auto *BarVal = Env.getValue(*BarDecl);
3302         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3303         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3304         EXPECT_EQ(FooVal, BarVal);
3305       });
3306 }
3307 
3308 TEST(TransferTest, IntegraltoBooleanCast) {
3309   std::string Code = R"(
3310     void target(int Foo) {
3311       bool Bar = Foo;
3312       // [[p]]
3313     }
3314   )";
3315   runDataflow(
3316       Code,
3317       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3318          ASTContext &ASTCtx) {
3319         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3320         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3321 
3322         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3323         ASSERT_THAT(FooDecl, NotNull());
3324 
3325         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3326         ASSERT_THAT(BarDecl, NotNull());
3327 
3328         const auto *FooVal = Env.getValue(*FooDecl);
3329         const auto *BarVal = Env.getValue(*BarDecl);
3330         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3331         EXPECT_TRUE(isa<BoolValue>(BarVal));
3332       });
3333 }
3334 
3335 TEST(TransferTest, IntegralToBooleanCastFromBool) {
3336   std::string Code = R"(
3337     void target(bool Foo) {
3338       int Zab = Foo;
3339       bool Bar = Zab;
3340       // [[p]]
3341     }
3342   )";
3343   runDataflow(
3344       Code,
3345       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3346          ASTContext &ASTCtx) {
3347         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3348         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3349 
3350         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3351         ASSERT_THAT(FooDecl, NotNull());
3352 
3353         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3354         ASSERT_THAT(BarDecl, NotNull());
3355 
3356         const auto *FooVal = Env.getValue(*FooDecl);
3357         const auto *BarVal = Env.getValue(*BarDecl);
3358         EXPECT_TRUE(isa<BoolValue>(FooVal));
3359         EXPECT_TRUE(isa<BoolValue>(BarVal));
3360         EXPECT_EQ(FooVal, BarVal);
3361       });
3362 }
3363 
3364 TEST(TransferTest, NullToPointerCast) {
3365   std::string Code = R"(
3366     using my_nullptr_t = decltype(nullptr);
3367     struct Baz {};
3368     void target() {
3369       int *FooX = nullptr;
3370       int *FooY = nullptr;
3371       bool **Bar = nullptr;
3372       Baz *Baz = nullptr;
3373       my_nullptr_t Null = 0;
3374       // [[p]]
3375     }
3376   )";
3377   runDataflow(
3378       Code,
3379       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3380          ASTContext &ASTCtx) {
3381         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3382         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3383 
3384         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
3385         ASSERT_THAT(FooXDecl, NotNull());
3386 
3387         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
3388         ASSERT_THAT(FooYDecl, NotNull());
3389 
3390         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3391         ASSERT_THAT(BarDecl, NotNull());
3392 
3393         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3394         ASSERT_THAT(BazDecl, NotNull());
3395 
3396         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
3397         ASSERT_THAT(NullDecl, NotNull());
3398 
3399         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
3400         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
3401         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3402         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
3403         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
3404 
3405         EXPECT_EQ(FooXVal, FooYVal);
3406         EXPECT_NE(FooXVal, BarVal);
3407         EXPECT_NE(FooXVal, BazVal);
3408         EXPECT_NE(BarVal, BazVal);
3409 
3410         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
3411         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
3412         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
3413 
3414         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
3415         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
3416         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
3417 
3418         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
3419         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
3420         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
3421 
3422         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
3423         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
3424         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
3425       });
3426 }
3427 
3428 TEST(TransferTest, PointerToMemberVariable) {
3429   std::string Code = R"(
3430     struct S {
3431       int i;
3432     };
3433     void target() {
3434       int S::*MemberPointer = &S::i;
3435       // [[p]]
3436     }
3437   )";
3438   runDataflow(
3439       Code,
3440       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3441          ASTContext &ASTCtx) {
3442         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3443 
3444         const ValueDecl *MemberPointerDecl =
3445             findValueDecl(ASTCtx, "MemberPointer");
3446         ASSERT_THAT(MemberPointerDecl, NotNull());
3447         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3448       });
3449 }
3450 
3451 TEST(TransferTest, PointerToMemberFunction) {
3452   std::string Code = R"(
3453     struct S {
3454       void Method();
3455     };
3456     void target() {
3457       void (S::*MemberPointer)() = &S::Method;
3458       // [[p]]
3459     }
3460   )";
3461   runDataflow(
3462       Code,
3463       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3464          ASTContext &ASTCtx) {
3465         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3466 
3467         const ValueDecl *MemberPointerDecl =
3468             findValueDecl(ASTCtx, "MemberPointer");
3469         ASSERT_THAT(MemberPointerDecl, NotNull());
3470         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3471       });
3472 }
3473 
3474 TEST(TransferTest, NullToMemberPointerCast) {
3475   std::string Code = R"(
3476     struct Foo {};
3477     void target() {
3478       int Foo::*MemberPointer = nullptr;
3479       // [[p]]
3480     }
3481   )";
3482   runDataflow(
3483       Code,
3484       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3485          ASTContext &ASTCtx) {
3486         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3487         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3488 
3489         const ValueDecl *MemberPointerDecl =
3490             findValueDecl(ASTCtx, "MemberPointer");
3491         ASSERT_THAT(MemberPointerDecl, NotNull());
3492         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3493       });
3494 }
3495 
3496 TEST(TransferTest, AddrOfValue) {
3497   std::string Code = R"(
3498     void target() {
3499       int Foo;
3500       int *Bar = &Foo;
3501       // [[p]]
3502     }
3503   )";
3504   runDataflow(
3505       Code,
3506       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3507          ASTContext &ASTCtx) {
3508         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3509         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3510 
3511         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3512         ASSERT_THAT(FooDecl, NotNull());
3513 
3514         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3515         ASSERT_THAT(BarDecl, NotNull());
3516 
3517         const auto *FooLoc =
3518             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3519         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3520         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3521       });
3522 }
3523 
3524 TEST(TransferTest, AddrOfReference) {
3525   std::string Code = R"(
3526     void target(int *Foo) {
3527       int *Bar = &(*Foo);
3528       // [[p]]
3529     }
3530   )";
3531   runDataflow(
3532       Code,
3533       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3534          ASTContext &ASTCtx) {
3535         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3536         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3537 
3538         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3539         ASSERT_THAT(FooDecl, NotNull());
3540 
3541         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3542         ASSERT_THAT(BarDecl, NotNull());
3543 
3544         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3545         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3546         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3547       });
3548 }
3549 
3550 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3551   std::string Code = R"(
3552     template <typename T>
3553     void target() {}
3554   )";
3555   ASSERT_THAT_ERROR(
3556       checkDataflowWithNoopAnalysis(Code),
3557       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3558 }
3559 
3560 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3561   std::string Code = R"(
3562     template <typename T>
3563     struct A {
3564       void target() {}
3565     };
3566   )";
3567   ASSERT_THAT_ERROR(
3568       checkDataflowWithNoopAnalysis(Code),
3569       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3570 }
3571 
3572 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3573   std::string Code = R"(
3574     struct A {};
3575 
3576     void target(A Foo, A Bar, bool Cond) {
3577       A Baz = Cond ?  Foo : Bar;
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 *FooDecl = findValueDecl(ASTCtx, "Foo");
3589         ASSERT_THAT(FooDecl, NotNull());
3590 
3591         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3592         ASSERT_THAT(BarDecl, NotNull());
3593 
3594         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3595         ASSERT_THAT(BazDecl, NotNull());
3596 
3597         const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
3598         const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
3599 
3600         const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
3601         ASSERT_THAT(BazVal, NotNull());
3602 
3603         EXPECT_NE(BazVal, FooVal);
3604         EXPECT_NE(BazVal, BarVal);
3605       });
3606 }
3607 
3608 TEST(TransferTest, VarDeclInDoWhile) {
3609   std::string Code = R"(
3610     void target(int *Foo) {
3611       do {
3612         int Bar = *Foo;
3613         // [[in_loop]]
3614       } while (false);
3615       (void)0;
3616       // [[after_loop]]
3617     }
3618   )";
3619   runDataflow(
3620       Code,
3621       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3622          ASTContext &ASTCtx) {
3623         const Environment &EnvInLoop =
3624             getEnvironmentAtAnnotation(Results, "in_loop");
3625         const Environment &EnvAfterLoop =
3626             getEnvironmentAtAnnotation(Results, "after_loop");
3627 
3628         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3629         ASSERT_THAT(FooDecl, NotNull());
3630 
3631         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3632         ASSERT_THAT(BarDecl, NotNull());
3633 
3634         const auto *FooVal =
3635             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3636         const auto *FooPointeeVal =
3637             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3638 
3639         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3640         EXPECT_EQ(BarVal, FooPointeeVal);
3641 
3642         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3643       });
3644 }
3645 
3646 TEST(TransferTest, UnreachableAfterWhileTrue) {
3647   std::string Code = R"(
3648     void target() {
3649       while (true) {}
3650       (void)0;
3651       /*[[p]]*/
3652     }
3653   )";
3654   runDataflow(
3655       Code,
3656       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3657          ASTContext &ASTCtx) {
3658         // The node after the while-true is pruned because it is trivially
3659         // known to be unreachable.
3660         ASSERT_TRUE(Results.empty());
3661       });
3662 }
3663 
3664 TEST(TransferTest, AggregateInitialization) {
3665   std::string BracesCode = R"(
3666     struct A {
3667       int Foo;
3668     };
3669 
3670     struct B {
3671       int Bar;
3672       A Baz;
3673       int Qux;
3674     };
3675 
3676     void target(int BarArg, int FooArg, int QuxArg) {
3677       B Quux{BarArg, {FooArg}, QuxArg};
3678       B OtherB;
3679       /*[[p]]*/
3680     }
3681   )";
3682   std::string BraceElisionCode = R"(
3683     struct A {
3684       int Foo;
3685     };
3686 
3687     struct B {
3688       int Bar;
3689       A Baz;
3690       int Qux;
3691     };
3692 
3693     void target(int BarArg, int FooArg, int QuxArg) {
3694       B Quux = {BarArg, FooArg, QuxArg};
3695       B OtherB;
3696       /*[[p]]*/
3697     }
3698   )";
3699   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3700     runDataflow(
3701         Code,
3702         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3703            ASTContext &ASTCtx) {
3704           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3705           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3706 
3707           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3708           ASSERT_THAT(FooDecl, NotNull());
3709 
3710           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3711           ASSERT_THAT(BarDecl, NotNull());
3712 
3713           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3714           ASSERT_THAT(BazDecl, NotNull());
3715 
3716           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3717           ASSERT_THAT(QuxDecl, NotNull());
3718 
3719           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3720           ASSERT_THAT(FooArgDecl, NotNull());
3721 
3722           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3723           ASSERT_THAT(BarArgDecl, NotNull());
3724 
3725           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3726           ASSERT_THAT(QuxArgDecl, NotNull());
3727 
3728           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3729           ASSERT_THAT(QuuxDecl, NotNull());
3730 
3731           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3732           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3733           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3734 
3735           const auto &QuuxLoc =
3736               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3737           const auto &BazLoc =
3738               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3739 
3740           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3741           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3742           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3743 
3744           // Check that fields initialized in an initializer list are always
3745           // modeled in other instances of the same type.
3746           const auto &OtherBLoc =
3747               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3748           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3749           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3750           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3751         });
3752   }
3753 }
3754 
3755 TEST(TransferTest, AggregateInitializationReferenceField) {
3756   std::string Code = R"(
3757     struct S {
3758       int &RefField;
3759     };
3760 
3761     void target(int i) {
3762       S s = { i };
3763       /*[[p]]*/
3764     }
3765   )";
3766   runDataflow(
3767       Code,
3768       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3769          ASTContext &ASTCtx) {
3770         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3771 
3772         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3773 
3774         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3775         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3776 
3777         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3778       });
3779 }
3780 
3781 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3782   std::string Code = R"(
3783     struct S {
3784       int i1;
3785       int i2;
3786     };
3787 
3788     void target(int i) {
3789       S s = { i };
3790       /*[[p]]*/
3791     }
3792   )";
3793   runDataflow(
3794       Code,
3795       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3796          ASTContext &ASTCtx) {
3797         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3798 
3799         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3800         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3801 
3802         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3803 
3804         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3805         auto &I1Value =
3806             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3807         EXPECT_EQ(&I1Value, &IValue);
3808         auto &I2Value =
3809             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3810         EXPECT_NE(&I2Value, &IValue);
3811       });
3812 }
3813 
3814 TEST(TransferTest, AggregateInitializationFunctionPointer) {
3815   // This is a repro for an assertion failure.
3816   // nullptr takes on the type of a const function pointer, but its type was
3817   // asserted to be equal to the *unqualified* type of Field, which no longer
3818   // included the const.
3819   std::string Code = R"(
3820     struct S {
3821       void (*const Field)();
3822     };
3823 
3824     void target() {
3825       S s{nullptr};
3826     }
3827   )";
3828   runDataflow(
3829       Code,
3830       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3831          ASTContext &ASTCtx) {});
3832 }
3833 
3834 TEST(TransferTest, AssignToUnionMember) {
3835   std::string Code = R"(
3836     union A {
3837       int Foo;
3838     };
3839 
3840     void target(int Bar) {
3841       A Baz;
3842       Baz.Foo = Bar;
3843       // [[p]]
3844     }
3845   )";
3846   runDataflow(
3847       Code,
3848       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3849          ASTContext &ASTCtx) {
3850         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3851         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3852 
3853         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3854         ASSERT_THAT(BazDecl, NotNull());
3855         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3856 
3857         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3858         FieldDecl *FooDecl = nullptr;
3859         for (FieldDecl *Field : BazFields) {
3860           if (Field->getNameAsString() == "Foo") {
3861             FooDecl = Field;
3862           } else {
3863             FAIL() << "Unexpected field: " << Field->getNameAsString();
3864           }
3865         }
3866         ASSERT_THAT(FooDecl, NotNull());
3867 
3868         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
3869             Env.getStorageLocation(*BazDecl));
3870         ASSERT_THAT(BazLoc, NotNull());
3871         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
3872 
3873         const auto *FooVal =
3874             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
3875 
3876         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3877         ASSERT_THAT(BarDecl, NotNull());
3878         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
3879         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3880 
3881         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
3882       });
3883 }
3884 
3885 TEST(TransferTest, AssignFromBoolLiteral) {
3886   std::string Code = R"(
3887     void target() {
3888       bool Foo = true;
3889       bool Bar = false;
3890       // [[p]]
3891     }
3892   )";
3893   runDataflow(
3894       Code,
3895       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3896          ASTContext &ASTCtx) {
3897         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3898         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3899 
3900         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3901         ASSERT_THAT(FooDecl, NotNull());
3902 
3903         const auto *FooVal =
3904             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3905         ASSERT_THAT(FooVal, NotNull());
3906 
3907         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3908         ASSERT_THAT(BarDecl, NotNull());
3909 
3910         const auto *BarVal =
3911             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3912         ASSERT_THAT(BarVal, NotNull());
3913 
3914         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3915         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3916       });
3917 }
3918 
3919 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3920   {
3921     std::string Code = R"(
3922     void target(bool Foo, bool Bar, bool Qux) {
3923       bool Baz = (Foo) && (Bar || Qux);
3924       // [[p]]
3925     }
3926   )";
3927     runDataflow(
3928         Code,
3929         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3930            ASTContext &ASTCtx) {
3931           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3932           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3933 
3934           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3935           ASSERT_THAT(FooDecl, NotNull());
3936 
3937           const auto *FooVal =
3938               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3939           ASSERT_THAT(FooVal, NotNull());
3940 
3941           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3942           ASSERT_THAT(BarDecl, NotNull());
3943 
3944           const auto *BarVal =
3945               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3946           ASSERT_THAT(BarVal, NotNull());
3947 
3948           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3949           ASSERT_THAT(QuxDecl, NotNull());
3950 
3951           const auto *QuxVal =
3952               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3953           ASSERT_THAT(QuxVal, NotNull());
3954 
3955           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3956           ASSERT_THAT(BazDecl, NotNull());
3957 
3958           const auto *BazVal =
3959               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3960           ASSERT_THAT(BazVal, NotNull());
3961           auto &A = Env.arena();
3962           EXPECT_EQ(&BazVal->formula(),
3963                     &A.makeAnd(FooVal->formula(),
3964                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3965         });
3966   }
3967 
3968   {
3969     std::string Code = R"(
3970     void target(bool Foo, bool Bar, bool Qux) {
3971       bool Baz = (Foo && Qux) || (Bar);
3972       // [[p]]
3973     }
3974   )";
3975     runDataflow(
3976         Code,
3977         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3978            ASTContext &ASTCtx) {
3979           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3980           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3981 
3982           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3983           ASSERT_THAT(FooDecl, NotNull());
3984 
3985           const auto *FooVal =
3986               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3987           ASSERT_THAT(FooVal, NotNull());
3988 
3989           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3990           ASSERT_THAT(BarDecl, NotNull());
3991 
3992           const auto *BarVal =
3993               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3994           ASSERT_THAT(BarVal, NotNull());
3995 
3996           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3997           ASSERT_THAT(QuxDecl, NotNull());
3998 
3999           const auto *QuxVal =
4000               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4001           ASSERT_THAT(QuxVal, NotNull());
4002 
4003           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4004           ASSERT_THAT(BazDecl, NotNull());
4005 
4006           const auto *BazVal =
4007               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4008           ASSERT_THAT(BazVal, NotNull());
4009           auto &A = Env.arena();
4010           EXPECT_EQ(&BazVal->formula(),
4011                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
4012                               BarVal->formula()));
4013         });
4014   }
4015 
4016   {
4017     std::string Code = R"(
4018       void target(bool A, bool B, bool C, bool D) {
4019         bool Foo = ((A && B) && C) && D;
4020         // [[p]]
4021       }
4022     )";
4023     runDataflow(
4024         Code,
4025         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4026            ASTContext &ASTCtx) {
4027           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4028           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4029 
4030           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
4031           ASSERT_THAT(ADecl, NotNull());
4032 
4033           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
4034           ASSERT_THAT(AVal, NotNull());
4035 
4036           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4037           ASSERT_THAT(BDecl, NotNull());
4038 
4039           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
4040           ASSERT_THAT(BVal, NotNull());
4041 
4042           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4043           ASSERT_THAT(CDecl, NotNull());
4044 
4045           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
4046           ASSERT_THAT(CVal, NotNull());
4047 
4048           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
4049           ASSERT_THAT(DDecl, NotNull());
4050 
4051           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
4052           ASSERT_THAT(DVal, NotNull());
4053 
4054           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4055           ASSERT_THAT(FooDecl, NotNull());
4056 
4057           const auto *FooVal =
4058               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4059           ASSERT_THAT(FooVal, NotNull());
4060           auto &A = Env.arena();
4061           EXPECT_EQ(
4062               &FooVal->formula(),
4063               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
4064                                    CVal->formula()),
4065                          DVal->formula()));
4066         });
4067   }
4068 }
4069 
4070 TEST(TransferTest, AssignFromBoolNegation) {
4071   std::string Code = R"(
4072     void target() {
4073       bool Foo = true;
4074       bool Bar = !(Foo);
4075       // [[p]]
4076     }
4077   )";
4078   runDataflow(
4079       Code,
4080       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4081          ASTContext &ASTCtx) {
4082         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4083         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4084 
4085         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4086         ASSERT_THAT(FooDecl, NotNull());
4087 
4088         const auto *FooVal =
4089             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4090         ASSERT_THAT(FooVal, NotNull());
4091 
4092         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4093         ASSERT_THAT(BarDecl, NotNull());
4094 
4095         const auto *BarVal =
4096             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4097         ASSERT_THAT(BarVal, NotNull());
4098         auto &A = Env.arena();
4099         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
4100       });
4101 }
4102 
4103 TEST(TransferTest, BuiltinExpect) {
4104   std::string Code = R"(
4105     void target(long Foo) {
4106       long Bar = __builtin_expect(Foo, true);
4107       /*[[p]]*/
4108     }
4109   )";
4110   runDataflow(
4111       Code,
4112       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4113          ASTContext &ASTCtx) {
4114         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4115         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4116 
4117         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4118         ASSERT_THAT(FooDecl, NotNull());
4119 
4120         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4121         ASSERT_THAT(BarDecl, NotNull());
4122 
4123         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4124       });
4125 }
4126 
4127 // `__builtin_expect` takes and returns a `long` argument, so other types
4128 // involve casts. This verifies that we identify the input and output in that
4129 // case.
4130 TEST(TransferTest, BuiltinExpectBoolArg) {
4131   std::string Code = R"(
4132     void target(bool Foo) {
4133       bool Bar = __builtin_expect(Foo, true);
4134       /*[[p]]*/
4135     }
4136   )";
4137   runDataflow(
4138       Code,
4139       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4140          ASTContext &ASTCtx) {
4141         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4142         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4143 
4144         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4145         ASSERT_THAT(FooDecl, NotNull());
4146 
4147         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4148         ASSERT_THAT(BarDecl, NotNull());
4149 
4150         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4151       });
4152 }
4153 
4154 TEST(TransferTest, BuiltinUnreachable) {
4155   std::string Code = R"(
4156     void target(bool Foo) {
4157       bool Bar = false;
4158       if (Foo)
4159         Bar = Foo;
4160       else
4161         __builtin_unreachable();
4162       (void)0;
4163       /*[[p]]*/
4164     }
4165   )";
4166   runDataflow(
4167       Code,
4168       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4169          ASTContext &ASTCtx) {
4170         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4171         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4172 
4173         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4174         ASSERT_THAT(FooDecl, NotNull());
4175 
4176         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4177         ASSERT_THAT(BarDecl, NotNull());
4178 
4179         // `__builtin_unreachable` promises that the code is
4180         // unreachable, so the compiler treats the "then" branch as the
4181         // only possible predecessor of this statement.
4182         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4183       });
4184 }
4185 
4186 TEST(TransferTest, BuiltinTrap) {
4187   std::string Code = R"(
4188     void target(bool Foo) {
4189       bool Bar = false;
4190       if (Foo)
4191         Bar = Foo;
4192       else
4193         __builtin_trap();
4194       (void)0;
4195       /*[[p]]*/
4196     }
4197   )";
4198   runDataflow(
4199       Code,
4200       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4201          ASTContext &ASTCtx) {
4202         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4203         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4204 
4205         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4206         ASSERT_THAT(FooDecl, NotNull());
4207 
4208         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4209         ASSERT_THAT(BarDecl, NotNull());
4210 
4211         // `__builtin_trap` ensures program termination, so only the
4212         // "then" branch is a predecessor of this statement.
4213         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4214       });
4215 }
4216 
4217 TEST(TransferTest, BuiltinDebugTrap) {
4218   std::string Code = R"(
4219     void target(bool Foo) {
4220       bool Bar = false;
4221       if (Foo)
4222         Bar = Foo;
4223       else
4224         __builtin_debugtrap();
4225       (void)0;
4226       /*[[p]]*/
4227     }
4228   )";
4229   runDataflow(
4230       Code,
4231       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4232          ASTContext &ASTCtx) {
4233         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4234         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4235 
4236         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4237         ASSERT_THAT(FooDecl, NotNull());
4238 
4239         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4240         ASSERT_THAT(BarDecl, NotNull());
4241 
4242         // `__builtin_debugtrap` doesn't ensure program termination.
4243         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4244       });
4245 }
4246 
4247 TEST(TransferTest, StaticIntSingleVarDecl) {
4248   std::string Code = R"(
4249     void target() {
4250       static int Foo;
4251       // [[p]]
4252     }
4253   )";
4254   runDataflow(
4255       Code,
4256       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4257          ASTContext &ASTCtx) {
4258         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4259         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4260 
4261         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4262         ASSERT_THAT(FooDecl, NotNull());
4263 
4264         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4265         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4266 
4267         const Value *FooVal = Env.getValue(*FooLoc);
4268         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4269       });
4270 }
4271 
4272 TEST(TransferTest, StaticIntGroupVarDecl) {
4273   std::string Code = R"(
4274     void target() {
4275       static int Foo, Bar;
4276       (void)0;
4277       // [[p]]
4278     }
4279   )";
4280   runDataflow(
4281       Code,
4282       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4283          ASTContext &ASTCtx) {
4284         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4285         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4286 
4287         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4288         ASSERT_THAT(FooDecl, NotNull());
4289 
4290         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4291         ASSERT_THAT(BarDecl, NotNull());
4292 
4293         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4294         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4295 
4296         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4297         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4298 
4299         const Value *FooVal = Env.getValue(*FooLoc);
4300         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4301 
4302         const Value *BarVal = Env.getValue(*BarLoc);
4303         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
4304 
4305         EXPECT_NE(FooVal, BarVal);
4306       });
4307 }
4308 
4309 TEST(TransferTest, GlobalIntVarDecl) {
4310   std::string Code = R"(
4311     static int Foo;
4312 
4313     void target() {
4314       int Bar = Foo;
4315       int Baz = Foo;
4316       // [[p]]
4317     }
4318   )";
4319   runDataflow(
4320       Code,
4321       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4322          ASTContext &ASTCtx) {
4323         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4324         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4325 
4326         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4327         ASSERT_THAT(BarDecl, NotNull());
4328 
4329         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4330         ASSERT_THAT(BazDecl, NotNull());
4331 
4332         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4333         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4334         EXPECT_EQ(BarVal, BazVal);
4335       });
4336 }
4337 
4338 TEST(TransferTest, StaticMemberIntVarDecl) {
4339   std::string Code = R"(
4340     struct A {
4341       static int Foo;
4342     };
4343 
4344     void target(A a) {
4345       int Bar = a.Foo;
4346       int Baz = a.Foo;
4347       // [[p]]
4348     }
4349   )";
4350   runDataflow(
4351       Code,
4352       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4353          ASTContext &ASTCtx) {
4354         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4355         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4356 
4357         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4358         ASSERT_THAT(BarDecl, NotNull());
4359 
4360         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4361         ASSERT_THAT(BazDecl, NotNull());
4362 
4363         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4364         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4365         EXPECT_EQ(BarVal, BazVal);
4366       });
4367 }
4368 
4369 TEST(TransferTest, StaticMemberRefVarDecl) {
4370   std::string Code = R"(
4371     struct A {
4372       static int &Foo;
4373     };
4374 
4375     void target(A a) {
4376       int Bar = a.Foo;
4377       int Baz = a.Foo;
4378       // [[p]]
4379     }
4380   )";
4381   runDataflow(
4382       Code,
4383       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4384          ASTContext &ASTCtx) {
4385         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4386         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4387 
4388         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4389         ASSERT_THAT(BarDecl, NotNull());
4390 
4391         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4392         ASSERT_THAT(BazDecl, NotNull());
4393 
4394         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4395         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4396         EXPECT_EQ(BarVal, BazVal);
4397       });
4398 }
4399 
4400 TEST(TransferTest, AssignMemberBeforeCopy) {
4401   std::string Code = R"(
4402     struct A {
4403       int Foo;
4404     };
4405 
4406     void target() {
4407       A A1;
4408       A A2;
4409       int Bar;
4410       A1.Foo = Bar;
4411       A2 = A1;
4412       // [[p]]
4413     }
4414   )";
4415   runDataflow(
4416       Code,
4417       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4418          ASTContext &ASTCtx) {
4419         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4420         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4421 
4422         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4423         ASSERT_THAT(FooDecl, NotNull());
4424 
4425         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4426         ASSERT_THAT(BarDecl, NotNull());
4427 
4428         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
4429         ASSERT_THAT(A1Decl, NotNull());
4430 
4431         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
4432         ASSERT_THAT(A2Decl, NotNull());
4433 
4434         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4435 
4436         const auto &A2Loc =
4437             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
4438         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
4439       });
4440 }
4441 
4442 TEST(TransferTest, BooleanEquality) {
4443   std::string Code = R"(
4444     void target(bool Bar) {
4445       bool Foo = true;
4446       if (Bar == Foo) {
4447         (void)0;
4448         /*[[p-then]]*/
4449       } else {
4450         (void)0;
4451         /*[[p-else]]*/
4452       }
4453     }
4454   )";
4455   runDataflow(
4456       Code,
4457       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4458          ASTContext &ASTCtx) {
4459         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4460         const Environment &EnvThen =
4461             getEnvironmentAtAnnotation(Results, "p-then");
4462         const Environment &EnvElse =
4463             getEnvironmentAtAnnotation(Results, "p-else");
4464 
4465         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4466         ASSERT_THAT(BarDecl, NotNull());
4467 
4468         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4469         EXPECT_TRUE(EnvThen.proves(BarValThen));
4470 
4471         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4472         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4473       });
4474 }
4475 
4476 TEST(TransferTest, BooleanInequality) {
4477   std::string Code = R"(
4478     void target(bool Bar) {
4479       bool Foo = true;
4480       if (Bar != Foo) {
4481         (void)0;
4482         /*[[p-then]]*/
4483       } else {
4484         (void)0;
4485         /*[[p-else]]*/
4486       }
4487     }
4488   )";
4489   runDataflow(
4490       Code,
4491       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4492          ASTContext &ASTCtx) {
4493         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4494         const Environment &EnvThen =
4495             getEnvironmentAtAnnotation(Results, "p-then");
4496         const Environment &EnvElse =
4497             getEnvironmentAtAnnotation(Results, "p-else");
4498 
4499         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4500         ASSERT_THAT(BarDecl, NotNull());
4501 
4502         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4503         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4504 
4505         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4506         EXPECT_TRUE(EnvElse.proves(BarValElse));
4507       });
4508 }
4509 
4510 TEST(TransferTest, IntegerLiteralEquality) {
4511   std::string Code = R"(
4512     void target() {
4513       bool equal = (42 == 42);
4514       // [[p]]
4515     }
4516   )";
4517   runDataflow(
4518       Code,
4519       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4520          ASTContext &ASTCtx) {
4521         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4522 
4523         auto &Equal =
4524             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4525         EXPECT_TRUE(Env.proves(Equal));
4526       });
4527 }
4528 
4529 TEST(TransferTest, CorrelatedBranches) {
4530   std::string Code = R"(
4531     void target(bool B, bool C) {
4532       if (B) {
4533         return;
4534       }
4535       (void)0;
4536       /*[[p0]]*/
4537       if (C) {
4538         B = true;
4539         /*[[p1]]*/
4540       }
4541       if (B) {
4542         (void)0;
4543         /*[[p2]]*/
4544       }
4545     }
4546   )";
4547   runDataflow(
4548       Code,
4549       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4550          ASTContext &ASTCtx) {
4551         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4552 
4553         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4554         ASSERT_THAT(CDecl, NotNull());
4555 
4556         {
4557           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4558           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4559           ASSERT_THAT(BDecl, NotNull());
4560           auto &BVal = getFormula(*BDecl, Env);
4561 
4562           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4563         }
4564 
4565         {
4566           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4567           auto &CVal = getFormula(*CDecl, Env);
4568           EXPECT_TRUE(Env.proves(CVal));
4569         }
4570 
4571         {
4572           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4573           auto &CVal = getFormula(*CDecl, Env);
4574           EXPECT_TRUE(Env.proves(CVal));
4575         }
4576       });
4577 }
4578 
4579 TEST(TransferTest, LoopWithAssignmentConverges) {
4580   std::string Code = R"(
4581     bool foo();
4582 
4583     void target() {
4584        do {
4585         bool Bar = foo();
4586         if (Bar) break;
4587         (void)Bar;
4588         /*[[p]]*/
4589       } while (true);
4590     }
4591   )";
4592   // The key property that we are verifying is implicit in `runDataflow` --
4593   // namely, that the analysis succeeds, rather than hitting the maximum number
4594   // of iterations.
4595   runDataflow(
4596       Code,
4597       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4598          ASTContext &ASTCtx) {
4599         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4600         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4601 
4602         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4603         ASSERT_THAT(BarDecl, NotNull());
4604 
4605         auto &BarVal = getFormula(*BarDecl, Env);
4606         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4607       });
4608 }
4609 
4610 TEST(TransferTest, LoopWithStagedAssignments) {
4611   std::string Code = R"(
4612     bool foo();
4613 
4614     void target() {
4615       bool Bar = false;
4616       bool Err = false;
4617       while (foo()) {
4618         if (Bar)
4619           Err = true;
4620         Bar = true;
4621         /*[[p]]*/
4622       }
4623     }
4624   )";
4625   runDataflow(
4626       Code,
4627       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4628          ASTContext &ASTCtx) {
4629         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4630         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4631 
4632         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4633         ASSERT_THAT(BarDecl, NotNull());
4634         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4635         ASSERT_THAT(ErrDecl, NotNull());
4636 
4637         auto &BarVal = getFormula(*BarDecl, Env);
4638         auto &ErrVal = getFormula(*ErrDecl, Env);
4639         EXPECT_TRUE(Env.proves(BarVal));
4640         // An unsound analysis, for example only evaluating the loop once, can
4641         // conclude that `Err` is false. So, we test that this conclusion is not
4642         // reached.
4643         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4644       });
4645 }
4646 
4647 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4648   std::string Code = R"(
4649     bool &foo();
4650 
4651     void target() {
4652        do {
4653         bool& Bar = foo();
4654         if (Bar) break;
4655         (void)Bar;
4656         /*[[p]]*/
4657       } while (true);
4658     }
4659   )";
4660   // The key property that we are verifying is that the analysis succeeds,
4661   // rather than hitting the maximum number of iterations.
4662   runDataflow(
4663       Code,
4664       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4665          ASTContext &ASTCtx) {
4666         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4667         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4668 
4669         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4670         ASSERT_THAT(BarDecl, NotNull());
4671 
4672         auto &BarVal = getFormula(*BarDecl, Env);
4673         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4674       });
4675 }
4676 
4677 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4678   std::string Code = R"(
4679     struct Lookup {
4680       int x;
4681     };
4682 
4683     void target(Lookup val, bool b) {
4684       const Lookup* l = nullptr;
4685       while (b) {
4686         l = &val;
4687         /*[[p-inner]]*/
4688       }
4689       (void)0;
4690       /*[[p-outer]]*/
4691     }
4692   )";
4693   // The key property that we are verifying is implicit in `runDataflow` --
4694   // namely, that the analysis succeeds, rather than hitting the maximum number
4695   // of iterations.
4696   runDataflow(
4697       Code,
4698       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4699          ASTContext &ASTCtx) {
4700         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4701         const Environment &InnerEnv =
4702             getEnvironmentAtAnnotation(Results, "p-inner");
4703         const Environment &OuterEnv =
4704             getEnvironmentAtAnnotation(Results, "p-outer");
4705 
4706         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4707         ASSERT_THAT(ValDecl, NotNull());
4708 
4709         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4710         ASSERT_THAT(LDecl, NotNull());
4711 
4712         // Inner.
4713         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4714         ASSERT_THAT(LVal, NotNull());
4715 
4716         EXPECT_EQ(&LVal->getPointeeLoc(),
4717                   InnerEnv.getStorageLocation(*ValDecl));
4718 
4719         // Outer.
4720         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4721         ASSERT_THAT(LVal, NotNull());
4722 
4723         // The loop body may not have been executed, so we should not conclude
4724         // that `l` points to `val`.
4725         EXPECT_NE(&LVal->getPointeeLoc(),
4726                   OuterEnv.getStorageLocation(*ValDecl));
4727       });
4728 }
4729 
4730 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4731   std::string Code = R"cc(
4732     bool some_condition();
4733 
4734     void target(int i1, int i2) {
4735       int *p = &i1;
4736       while (true) {
4737         (void)*p;
4738         if (some_condition())
4739           p = &i1;
4740         else
4741           p = &i2;
4742       }
4743     }
4744   )cc";
4745   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4746 }
4747 
4748 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4749   std::string Code = R"cc(
4750     struct Lookup {
4751       int x;
4752     };
4753 
4754     bool some_condition();
4755 
4756     void target(Lookup l1, Lookup l2) {
4757       Lookup *l = &l1;
4758       while (true) {
4759         (void)l->x;
4760         if (some_condition())
4761           l = &l1;
4762         else
4763           l = &l2;
4764       }
4765     }
4766   )cc";
4767   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4768 }
4769 
4770 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4771   std::string Code = R"cc(
4772     bool foo();
4773 
4774     void target() {
4775       bool c = false;
4776       while (foo() || foo()) {
4777         c = true;
4778       }
4779     }
4780   )cc";
4781   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4782 }
4783 
4784 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
4785   // Check that we can prove `b` is always false in the loop.
4786   // This test exercises the logic in `widenDistinctValues()` that preserves
4787   // information if the boolean can be proved to be either true or false in both
4788   // the previous and current iteration.
4789   std::string Code = R"cc(
4790     int return_int();
4791     void target() {
4792       bool b = return_int() == 0;
4793       if (b) return;
4794       while (true) {
4795         b;
4796         // [[p]]
4797         b = return_int() == 0;
4798         if (b) return;
4799       }
4800     }
4801   )cc";
4802   runDataflow(
4803       Code,
4804       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4805          ASTContext &ASTCtx) {
4806         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4807         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
4808         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
4809       });
4810 }
4811 
4812 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4813   std::string Code = R"cc(
4814     union Union {
4815       int A;
4816       float B;
4817     };
4818 
4819     void foo() {
4820       Union A;
4821       Union B;
4822       A = B;
4823     }
4824   )cc";
4825   // This is a crash regression test when calling the transfer function on a
4826   // `CXXThisExpr` that refers to a union.
4827   runDataflow(
4828       Code,
4829       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4830          ASTContext &) {},
4831       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4832 }
4833 
4834 TEST(TransferTest, DoesNotCrashOnNullChildren) {
4835   std::string Code = (CoroutineLibrary + R"cc(
4836     task target() noexcept {
4837       co_return;
4838     }
4839   )cc")
4840                          .str();
4841   // This is a crash regression test when calling `AdornedCFG::build` on a
4842   // statement (in this case, the `CoroutineBodyStmt`) with null children.
4843   runDataflow(
4844       Code,
4845       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4846          ASTContext &) {},
4847       LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true);
4848 }
4849 
4850 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4851   std::string Code = R"(
4852     struct A {
4853       int Foo;
4854       int Bar;
4855     };
4856 
4857     void target() {
4858       int Qux;
4859       A Baz;
4860       Baz.Foo = Qux;
4861       auto &FooRef = Baz.Foo;
4862       auto &BarRef = Baz.Bar;
4863       auto &[BoundFooRef, BoundBarRef] = Baz;
4864       // [[p]]
4865     }
4866   )";
4867   runDataflow(
4868       Code,
4869       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4870          ASTContext &ASTCtx) {
4871         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4872         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4873 
4874         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4875         ASSERT_THAT(FooRefDecl, NotNull());
4876 
4877         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4878         ASSERT_THAT(BarRefDecl, NotNull());
4879 
4880         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4881         ASSERT_THAT(QuxDecl, NotNull());
4882 
4883         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4884         ASSERT_THAT(BoundFooRefDecl, NotNull());
4885 
4886         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4887         ASSERT_THAT(BoundBarRefDecl, NotNull());
4888 
4889         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4890         ASSERT_THAT(FooRefLoc, NotNull());
4891 
4892         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4893         ASSERT_THAT(BarRefLoc, NotNull());
4894 
4895         const Value *QuxVal = Env.getValue(*QuxDecl);
4896         ASSERT_THAT(QuxVal, NotNull());
4897 
4898         const StorageLocation *BoundFooRefLoc =
4899             Env.getStorageLocation(*BoundFooRefDecl);
4900         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4901 
4902         const StorageLocation *BoundBarRefLoc =
4903             Env.getStorageLocation(*BoundBarRefDecl);
4904         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4905 
4906         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4907       });
4908 }
4909 
4910 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4911   std::string Code = R"(
4912     struct A {
4913       int &Foo;
4914       int &Bar;
4915     };
4916 
4917     void target(A Baz) {
4918       int Qux;
4919       Baz.Foo = Qux;
4920       auto &FooRef = Baz.Foo;
4921       auto &BarRef = Baz.Bar;
4922       auto &[BoundFooRef, BoundBarRef] = Baz;
4923       // [[p]]
4924     }
4925   )";
4926   runDataflow(
4927       Code,
4928       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4929          ASTContext &ASTCtx) {
4930         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4931         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4932 
4933         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4934         ASSERT_THAT(FooRefDecl, NotNull());
4935 
4936         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4937         ASSERT_THAT(BarRefDecl, NotNull());
4938 
4939         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4940         ASSERT_THAT(QuxDecl, NotNull());
4941 
4942         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4943         ASSERT_THAT(BoundFooRefDecl, NotNull());
4944 
4945         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4946         ASSERT_THAT(BoundBarRefDecl, NotNull());
4947 
4948         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4949         ASSERT_THAT(FooRefLoc, NotNull());
4950 
4951         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4952         ASSERT_THAT(BarRefLoc, NotNull());
4953 
4954         const Value *QuxVal = Env.getValue(*QuxDecl);
4955         ASSERT_THAT(QuxVal, NotNull());
4956 
4957         const StorageLocation *BoundFooRefLoc =
4958             Env.getStorageLocation(*BoundFooRefDecl);
4959         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4960 
4961         const StorageLocation *BoundBarRefLoc =
4962             Env.getStorageLocation(*BoundBarRefDecl);
4963         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4964 
4965         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4966       });
4967 }
4968 
4969 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4970   std::string Code = R"(
4971     struct A {
4972       int Foo;
4973       int Bar;
4974     };
4975 
4976     void target() {
4977       int Qux;
4978       A Baz;
4979       Baz.Foo = Qux;
4980       auto &FooRef = Baz.Foo;
4981       auto &BarRef = Baz.Bar;
4982       auto [BoundFoo, BoundBar] = Baz;
4983       // [[p]]
4984     }
4985   )";
4986   runDataflow(
4987       Code,
4988       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4989          ASTContext &ASTCtx) {
4990         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4991         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4992 
4993         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4994         ASSERT_THAT(FooRefDecl, NotNull());
4995 
4996         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4997         ASSERT_THAT(BarRefDecl, NotNull());
4998 
4999         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5000         ASSERT_THAT(BoundFooDecl, NotNull());
5001 
5002         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5003         ASSERT_THAT(BoundBarDecl, NotNull());
5004 
5005         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5006         ASSERT_THAT(QuxDecl, NotNull());
5007 
5008         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5009         ASSERT_THAT(FooRefLoc, NotNull());
5010 
5011         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5012         ASSERT_THAT(BarRefLoc, NotNull());
5013 
5014         const Value *QuxVal = Env.getValue(*QuxDecl);
5015         ASSERT_THAT(QuxVal, NotNull());
5016 
5017         const StorageLocation *BoundFooLoc =
5018             Env.getStorageLocation(*BoundFooDecl);
5019         EXPECT_NE(BoundFooLoc, FooRefLoc);
5020 
5021         const StorageLocation *BoundBarLoc =
5022             Env.getStorageLocation(*BoundBarDecl);
5023         EXPECT_NE(BoundBarLoc, BarRefLoc);
5024 
5025         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
5026       });
5027 }
5028 
5029 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
5030   std::string Code = R"(
5031     namespace std {
5032     using size_t = int;
5033     template <class> struct tuple_size;
5034     template <std::size_t, class> struct tuple_element;
5035     template <class...> class tuple;
5036 
5037     namespace {
5038     template <class T, T v>
5039     struct size_helper { static const T value = v; };
5040     } // namespace
5041 
5042     template <class... T>
5043     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5044 
5045     template <std::size_t I, class... T>
5046     struct tuple_element<I, tuple<T...>> {
5047       using type =  __type_pack_element<I, T...>;
5048     };
5049 
5050     template <class...> class tuple {};
5051 
5052     template <std::size_t I, class... T>
5053     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5054     } // namespace std
5055 
5056     std::tuple<bool, int> makeTuple();
5057 
5058     void target(bool B) {
5059       auto [BoundFoo, BoundBar] = makeTuple();
5060       bool Baz;
5061       // Include if-then-else to test interaction of `BindingDecl` with join.
5062       if (B) {
5063         Baz = BoundFoo;
5064         (void)BoundBar;
5065         // [[p1]]
5066       } else {
5067         Baz = BoundFoo;
5068       }
5069       (void)0;
5070       // [[p2]]
5071     }
5072   )";
5073   runDataflow(
5074       Code,
5075       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5076          ASTContext &ASTCtx) {
5077         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5078         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5079 
5080         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5081         ASSERT_THAT(BoundFooDecl, NotNull());
5082 
5083         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5084         ASSERT_THAT(BoundBarDecl, NotNull());
5085 
5086         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5087         ASSERT_THAT(BazDecl, NotNull());
5088 
5089         // BindingDecls always map to references -- either lvalue or rvalue, so
5090         // we still need to skip here.
5091         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5092         ASSERT_THAT(BoundFooValue, NotNull());
5093         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5094 
5095         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5096         ASSERT_THAT(BoundBarValue, NotNull());
5097         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5098 
5099         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
5100         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5101 
5102         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5103 
5104         // Test that `BoundFooDecl` retains the value we expect, after the join.
5105         BoundFooValue = Env2.getValue(*BoundFooDecl);
5106         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5107       });
5108 }
5109 
5110 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
5111   std::string Code = R"(
5112     namespace std {
5113     using size_t = int;
5114     template <class> struct tuple_size;
5115     template <std::size_t, class> struct tuple_element;
5116     template <class...> class tuple;
5117 
5118     namespace {
5119     template <class T, T v>
5120     struct size_helper { static const T value = v; };
5121     } // namespace
5122 
5123     template <class... T>
5124     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5125 
5126     template <std::size_t I, class... T>
5127     struct tuple_element<I, tuple<T...>> {
5128       using type =  __type_pack_element<I, T...>;
5129     };
5130 
5131     template <class...> class tuple {};
5132 
5133     template <std::size_t I, class... T>
5134     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5135     } // namespace std
5136 
5137     std::tuple<bool, int> &getTuple();
5138 
5139     void target(bool B) {
5140       auto &[BoundFoo, BoundBar] = getTuple();
5141       bool Baz;
5142       // Include if-then-else to test interaction of `BindingDecl` with join.
5143       if (B) {
5144         Baz = BoundFoo;
5145         (void)BoundBar;
5146         // [[p1]]
5147       } else {
5148         Baz = BoundFoo;
5149       }
5150       (void)0;
5151       // [[p2]]
5152     }
5153   )";
5154   runDataflow(
5155       Code,
5156       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5157          ASTContext &ASTCtx) {
5158         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5159         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5160 
5161         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5162         ASSERT_THAT(BoundFooDecl, NotNull());
5163 
5164         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5165         ASSERT_THAT(BoundBarDecl, NotNull());
5166 
5167         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5168         ASSERT_THAT(BazDecl, NotNull());
5169 
5170         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5171         ASSERT_THAT(BoundFooValue, NotNull());
5172         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5173 
5174         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5175         ASSERT_THAT(BoundBarValue, NotNull());
5176         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5177 
5178         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
5179         // works as expected. We don't test aliasing properties of the
5180         // reference, because we don't model `std::get` and so have no way to
5181         // equate separate references into the tuple.
5182         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5183 
5184         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5185 
5186         // Test that `BoundFooDecl` retains the value we expect, after the join.
5187         BoundFooValue = Env2.getValue(*BoundFooDecl);
5188         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5189       });
5190 }
5191 
5192 TEST(TransferTest, BinaryOperatorComma) {
5193   std::string Code = R"(
5194     void target(int Foo, int Bar) {
5195       int &Baz = (Foo, Bar);
5196       // [[p]]
5197     }
5198   )";
5199   runDataflow(
5200       Code,
5201       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5202          ASTContext &ASTCtx) {
5203         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5204         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5205 
5206         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5207         ASSERT_THAT(BarDecl, NotNull());
5208 
5209         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5210         ASSERT_THAT(BazDecl, NotNull());
5211 
5212         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
5213         ASSERT_THAT(BarLoc, NotNull());
5214 
5215         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
5216         EXPECT_EQ(BazLoc, BarLoc);
5217       });
5218 }
5219 
5220 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
5221   std::string Code = R"(
5222     void target(bool Foo) {
5223       if (Foo) {
5224         (void)0;
5225         // [[if_then]]
5226       } else {
5227         (void)0;
5228         // [[if_else]]
5229       }
5230     }
5231   )";
5232   runDataflow(
5233       Code,
5234       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5235          ASTContext &ASTCtx) {
5236         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
5237         const Environment &ThenEnv =
5238             getEnvironmentAtAnnotation(Results, "if_then");
5239         const Environment &ElseEnv =
5240             getEnvironmentAtAnnotation(Results, "if_else");
5241 
5242         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5243         ASSERT_THAT(FooDecl, NotNull());
5244 
5245         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
5246         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
5247 
5248         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
5249         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
5250       });
5251 }
5252 
5253 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
5254   std::string Code = R"(
5255     void target(bool Foo) {
5256       while (Foo) {
5257         (void)0;
5258         // [[loop_body]]
5259       }
5260       (void)0;
5261       // [[after_loop]]
5262     }
5263   )";
5264   runDataflow(
5265       Code,
5266       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5267          ASTContext &ASTCtx) {
5268         ASSERT_THAT(Results.keys(),
5269                     UnorderedElementsAre("loop_body", "after_loop"));
5270         const Environment &LoopBodyEnv =
5271             getEnvironmentAtAnnotation(Results, "loop_body");
5272         const Environment &AfterLoopEnv =
5273             getEnvironmentAtAnnotation(Results, "after_loop");
5274 
5275         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5276         ASSERT_THAT(FooDecl, NotNull());
5277 
5278         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
5279         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5280 
5281         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5282         EXPECT_TRUE(
5283             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5284       });
5285 }
5286 
5287 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
5288   std::string Code = R"(
5289     void target(bool Foo) {
5290       bool Bar = true;
5291       do {
5292         (void)0;
5293         // [[loop_body]]
5294         Bar = false;
5295       } while (Foo);
5296       (void)0;
5297       // [[after_loop]]
5298     }
5299   )";
5300   runDataflow(
5301       Code,
5302       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5303          ASTContext &ASTCtx) {
5304         ASSERT_THAT(Results.keys(),
5305                     UnorderedElementsAre("loop_body", "after_loop"));
5306         const Environment &LoopBodyEnv =
5307             getEnvironmentAtAnnotation(Results, "loop_body");
5308         const Environment &AfterLoopEnv =
5309             getEnvironmentAtAnnotation(Results, "after_loop");
5310         auto &A = AfterLoopEnv.arena();
5311 
5312         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5313         ASSERT_THAT(FooDecl, NotNull());
5314 
5315         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5316         ASSERT_THAT(BarDecl, NotNull());
5317 
5318         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5319         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
5320         EXPECT_TRUE(
5321             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
5322 
5323         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5324         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
5325         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
5326         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
5327       });
5328 }
5329 
5330 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
5331   std::string Code = R"(
5332     void target(bool Foo) {
5333       for (; Foo;) {
5334         (void)0;
5335         // [[loop_body]]
5336       }
5337       (void)0;
5338       // [[after_loop]]
5339     }
5340   )";
5341   runDataflow(
5342       Code,
5343       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5344          ASTContext &ASTCtx) {
5345         ASSERT_THAT(Results.keys(),
5346                     UnorderedElementsAre("loop_body", "after_loop"));
5347         const Environment &LoopBodyEnv =
5348             getEnvironmentAtAnnotation(Results, "loop_body");
5349         const Environment &AfterLoopEnv =
5350             getEnvironmentAtAnnotation(Results, "after_loop");
5351 
5352         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5353         ASSERT_THAT(FooDecl, NotNull());
5354 
5355         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5356         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5357 
5358         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5359         EXPECT_TRUE(
5360             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5361       });
5362 }
5363 
5364 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
5365   std::string Code = R"(
5366     void target(bool Foo) {
5367       for (;;) {
5368         (void)0;
5369         // [[loop_body]]
5370       }
5371     }
5372   )";
5373   runDataflow(
5374       Code,
5375       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5376          ASTContext &ASTCtx) {
5377         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
5378         const Environment &LoopBodyEnv =
5379             getEnvironmentAtAnnotation(Results, "loop_body");
5380 
5381         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5382         ASSERT_THAT(FooDecl, NotNull());
5383 
5384         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5385         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
5386       });
5387 }
5388 
5389 TEST(TransferTest, ContextSensitiveOptionDisabled) {
5390   std::string Code = R"(
5391     bool GiveBool();
5392     void SetBool(bool &Var) { Var = true; }
5393 
5394     void target() {
5395       bool Foo = GiveBool();
5396       SetBool(Foo);
5397       // [[p]]
5398     }
5399   )";
5400   runDataflow(
5401       Code,
5402       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5403          ASTContext &ASTCtx) {
5404         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5405         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5406 
5407         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5408         ASSERT_THAT(FooDecl, NotNull());
5409 
5410         auto &FooVal = getFormula(*FooDecl, Env);
5411         EXPECT_FALSE(Env.proves(FooVal));
5412         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5413       },
5414       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
5415 }
5416 
5417 TEST(TransferTest, ContextSensitiveReturnReference) {
5418   std::string Code = R"(
5419     class S {};
5420     S& target(bool b, S &s) {
5421       return s;
5422       // [[p]]
5423     }
5424   )";
5425   runDataflow(
5426       Code,
5427       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5428          ASTContext &ASTCtx) {
5429         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5430 
5431         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5432         ASSERT_THAT(SDecl, NotNull());
5433 
5434         auto *SLoc = Env.getStorageLocation(*SDecl);
5435         ASSERT_THAT(SLoc, NotNull());
5436 
5437         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
5438       },
5439       {BuiltinOptions{ContextSensitiveOptions{}}});
5440 }
5441 
5442 // This test is a regression test, based on a real crash.
5443 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
5444   std::string Code = R"(
5445     class S {};
5446     S& target(bool b, S &s) {
5447       return b ? s : s;
5448       // [[p]]
5449     }
5450   )";
5451   runDataflow(
5452       Code,
5453       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5454          ASTContext &ASTCtx) {
5455         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5456         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5457 
5458         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5459         ASSERT_THAT(SDecl, NotNull());
5460 
5461         auto *SLoc = Env.getStorageLocation(*SDecl);
5462         ASSERT_THAT(SLoc, NotNull());
5463         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
5464 
5465         auto *Loc = Env.getReturnStorageLocation();
5466         ASSERT_THAT(Loc, NotNull());
5467         EXPECT_THAT(Env.getValue(*Loc), NotNull());
5468 
5469         // TODO: We would really like to make this stronger assertion, but that
5470         // doesn't work because we don't propagate values correctly through
5471         // the conditional operator yet.
5472         // ASSERT_THAT(Loc, Eq(SLoc));
5473       },
5474       {BuiltinOptions{ContextSensitiveOptions{}}});
5475 }
5476 
5477 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5478   std::string Code = R"(
5479     class S {};
5480     S &callee(bool b, S &s1_parm, S &s2_parm) {
5481       if (b)
5482         return s1_parm;
5483       else
5484         return s2_parm;
5485     }
5486     void target(bool b) {
5487       S s1;
5488       S s2;
5489       S &return_s1 = s1;
5490       S &return_s2 = s2;
5491       S &return_dont_know = callee(b, s1, s2);
5492       // [[p]]
5493     }
5494   )";
5495   runDataflow(
5496       Code,
5497       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5498          ASTContext &ASTCtx) {
5499         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5500 
5501         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
5502         ASSERT_THAT(S1, NotNull());
5503         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
5504         ASSERT_THAT(S2, NotNull());
5505         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
5506         ASSERT_THAT(ReturnS1, NotNull());
5507         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
5508         ASSERT_THAT(ReturnS2, NotNull());
5509         const ValueDecl *ReturnDontKnow =
5510             findValueDecl(ASTCtx, "return_dont_know");
5511         ASSERT_THAT(ReturnDontKnow, NotNull());
5512 
5513         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
5514         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
5515 
5516         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
5517         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
5518 
5519         // In the case where we don't have a consistent storage location for
5520         // the return value, the framework creates a new storage location, which
5521         // should be different from the storage locations of `s1` and `s2`.
5522         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
5523         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
5524       },
5525       {BuiltinOptions{ContextSensitiveOptions{}}});
5526 }
5527 
5528 TEST(TransferTest, ContextSensitiveDepthZero) {
5529   std::string Code = R"(
5530     bool GiveBool();
5531     void SetBool(bool &Var) { Var = true; }
5532 
5533     void target() {
5534       bool Foo = GiveBool();
5535       SetBool(Foo);
5536       // [[p]]
5537     }
5538   )";
5539   runDataflow(
5540       Code,
5541       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5542          ASTContext &ASTCtx) {
5543         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5544         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5545 
5546         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5547         ASSERT_THAT(FooDecl, NotNull());
5548 
5549         auto &FooVal = getFormula(*FooDecl, Env);
5550         EXPECT_FALSE(Env.proves(FooVal));
5551         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5552       },
5553       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
5554 }
5555 
5556 TEST(TransferTest, ContextSensitiveSetTrue) {
5557   std::string Code = R"(
5558     bool GiveBool();
5559     void SetBool(bool &Var) { Var = true; }
5560 
5561     void target() {
5562       bool Foo = GiveBool();
5563       SetBool(Foo);
5564       // [[p]]
5565     }
5566   )";
5567   runDataflow(
5568       Code,
5569       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5570          ASTContext &ASTCtx) {
5571         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5572         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5573 
5574         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5575         ASSERT_THAT(FooDecl, NotNull());
5576 
5577         auto &FooVal = getFormula(*FooDecl, Env);
5578         EXPECT_TRUE(Env.proves(FooVal));
5579       },
5580       {BuiltinOptions{ContextSensitiveOptions{}}});
5581 }
5582 
5583 TEST(TransferTest, ContextSensitiveSetFalse) {
5584   std::string Code = R"(
5585     bool GiveBool();
5586     void SetBool(bool &Var) { Var = false; }
5587 
5588     void target() {
5589       bool Foo = GiveBool();
5590       SetBool(Foo);
5591       // [[p]]
5592     }
5593   )";
5594   runDataflow(
5595       Code,
5596       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5597          ASTContext &ASTCtx) {
5598         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5599         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5600 
5601         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5602         ASSERT_THAT(FooDecl, NotNull());
5603 
5604         auto &FooVal = getFormula(*FooDecl, Env);
5605         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5606       },
5607       {BuiltinOptions{ContextSensitiveOptions{}}});
5608 }
5609 
5610 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5611   std::string Code = R"(
5612     bool GiveBool();
5613     void SetBool(bool &Var, bool Val) { Var = Val; }
5614 
5615     void target() {
5616       bool Foo = GiveBool();
5617       bool Bar = GiveBool();
5618       SetBool(Foo, true);
5619       SetBool(Bar, false);
5620       // [[p]]
5621     }
5622   )";
5623   runDataflow(
5624       Code,
5625       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5626          ASTContext &ASTCtx) {
5627         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5628         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5629         auto &A = Env.arena();
5630 
5631         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5632         ASSERT_THAT(FooDecl, NotNull());
5633 
5634         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5635         ASSERT_THAT(BarDecl, NotNull());
5636 
5637         auto &FooVal = getFormula(*FooDecl, Env);
5638         EXPECT_TRUE(Env.proves(FooVal));
5639         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
5640 
5641         auto &BarVal = getFormula(*BarDecl, Env);
5642         EXPECT_FALSE(Env.proves(BarVal));
5643         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
5644       },
5645       {BuiltinOptions{ContextSensitiveOptions{}}});
5646 }
5647 
5648 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
5649   std::string Code = R"(
5650     bool GiveBool();
5651     void SetBool1(bool &Var) { Var = true; }
5652     void SetBool2(bool &Var) { SetBool1(Var); }
5653 
5654     void target() {
5655       bool Foo = GiveBool();
5656       SetBool2(Foo);
5657       // [[p]]
5658     }
5659   )";
5660   runDataflow(
5661       Code,
5662       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5663          ASTContext &ASTCtx) {
5664         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5665         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5666 
5667         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5668         ASSERT_THAT(FooDecl, NotNull());
5669 
5670         auto &FooVal = getFormula(*FooDecl, Env);
5671         EXPECT_FALSE(Env.proves(FooVal));
5672         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5673       },
5674       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5675 }
5676 
5677 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5678   std::string Code = R"(
5679     bool GiveBool();
5680     void SetBool1(bool &Var) { Var = true; }
5681     void SetBool2(bool &Var) { SetBool1(Var); }
5682 
5683     void target() {
5684       bool Foo = GiveBool();
5685       SetBool2(Foo);
5686       // [[p]]
5687     }
5688   )";
5689   runDataflow(
5690       Code,
5691       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5692          ASTContext &ASTCtx) {
5693         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5694         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5695 
5696         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5697         ASSERT_THAT(FooDecl, NotNull());
5698 
5699         auto &FooVal = getFormula(*FooDecl, Env);
5700         EXPECT_TRUE(Env.proves(FooVal));
5701       },
5702       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5703 }
5704 
5705 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5706   std::string Code = R"(
5707     bool GiveBool();
5708     void SetBool1(bool &Var) { Var = true; }
5709     void SetBool2(bool &Var) { SetBool1(Var); }
5710     void SetBool3(bool &Var) { SetBool2(Var); }
5711 
5712     void target() {
5713       bool Foo = GiveBool();
5714       SetBool3(Foo);
5715       // [[p]]
5716     }
5717   )";
5718   runDataflow(
5719       Code,
5720       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5721          ASTContext &ASTCtx) {
5722         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5723         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5724 
5725         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5726         ASSERT_THAT(FooDecl, NotNull());
5727 
5728         auto &FooVal = getFormula(*FooDecl, Env);
5729         EXPECT_FALSE(Env.proves(FooVal));
5730         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5731       },
5732       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5733 }
5734 
5735 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5736   std::string Code = R"(
5737     bool GiveBool();
5738     void SetBool1(bool &Var) { Var = true; }
5739     void SetBool2(bool &Var) { SetBool1(Var); }
5740     void SetBool3(bool &Var) { SetBool2(Var); }
5741 
5742     void target() {
5743       bool Foo = GiveBool();
5744       SetBool3(Foo);
5745       // [[p]]
5746     }
5747   )";
5748   runDataflow(
5749       Code,
5750       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5751          ASTContext &ASTCtx) {
5752         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5753         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5754 
5755         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5756         ASSERT_THAT(FooDecl, NotNull());
5757 
5758         auto &FooVal = getFormula(*FooDecl, Env);
5759         EXPECT_TRUE(Env.proves(FooVal));
5760       },
5761       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5762 }
5763 
5764 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5765   std::string Code = R"(
5766     bool Pong(bool X, bool Y);
5767 
5768     bool Ping(bool X, bool Y) {
5769       if (X) {
5770         return Y;
5771       } else {
5772         return Pong(!X, Y);
5773       }
5774     }
5775 
5776     bool Pong(bool X, bool Y) {
5777       if (Y) {
5778         return X;
5779       } else {
5780         return Ping(X, !Y);
5781       }
5782     }
5783 
5784     void target() {
5785       bool Foo = Ping(false, false);
5786       // [[p]]
5787     }
5788   )";
5789   runDataflow(
5790       Code,
5791       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5792          ASTContext &ASTCtx) {
5793         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5794         // The analysis doesn't crash...
5795         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5796 
5797         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5798         ASSERT_THAT(FooDecl, NotNull());
5799 
5800         auto &FooVal = getFormula(*FooDecl, Env);
5801         // ... but it also can't prove anything here.
5802         EXPECT_FALSE(Env.proves(FooVal));
5803         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5804       },
5805       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5806 }
5807 
5808 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5809   std::string Code = R"(
5810     void SetBools(bool &Var1, bool &Var2) {
5811       Var1 = true;
5812       Var2 = false;
5813     }
5814 
5815     void target() {
5816       bool Foo = false;
5817       bool Bar = true;
5818       SetBools(Foo, Bar);
5819       // [[p]]
5820     }
5821   )";
5822   runDataflow(
5823       Code,
5824       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5825          ASTContext &ASTCtx) {
5826         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5827         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5828 
5829         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5830         ASSERT_THAT(FooDecl, NotNull());
5831 
5832         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5833         ASSERT_THAT(BarDecl, NotNull());
5834 
5835         auto &FooVal = getFormula(*FooDecl, Env);
5836         EXPECT_TRUE(Env.proves(FooVal));
5837         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5838 
5839         auto &BarVal = getFormula(*BarDecl, Env);
5840         EXPECT_FALSE(Env.proves(BarVal));
5841         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5842       },
5843       {BuiltinOptions{ContextSensitiveOptions{}}});
5844 }
5845 
5846 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5847   std::string Code = R"(
5848     void IfCond(bool Cond, bool &Then, bool &Else) {
5849       if (Cond) {
5850         Then = true;
5851       } else {
5852         Else = true;
5853       }
5854     }
5855 
5856     void target() {
5857       bool Foo = false;
5858       bool Bar = false;
5859       bool Baz = false;
5860       IfCond(Foo, Bar, Baz);
5861       // [[p]]
5862     }
5863   )";
5864   runDataflow(
5865       Code,
5866       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5867          ASTContext &ASTCtx) {
5868         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5869         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5870 
5871         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5872         ASSERT_THAT(BarDecl, NotNull());
5873 
5874         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5875         ASSERT_THAT(BazDecl, NotNull());
5876 
5877         auto &BarVal = getFormula(*BarDecl, Env);
5878         EXPECT_FALSE(Env.proves(BarVal));
5879         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5880 
5881         auto &BazVal = getFormula(*BazDecl, Env);
5882         EXPECT_TRUE(Env.proves(BazVal));
5883         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5884       },
5885       {BuiltinOptions{ContextSensitiveOptions{}}});
5886 }
5887 
5888 TEST(TransferTest, ContextSensitiveReturnVoid) {
5889   std::string Code = R"(
5890     void Noop() { return; }
5891 
5892     void target() {
5893       Noop();
5894       // [[p]]
5895     }
5896   )";
5897   runDataflow(
5898       Code,
5899       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5900          ASTContext &ASTCtx) {
5901         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5902         // This just tests that the analysis doesn't crash.
5903       },
5904       {BuiltinOptions{ContextSensitiveOptions{}}});
5905 }
5906 
5907 TEST(TransferTest, ContextSensitiveReturnTrue) {
5908   std::string Code = R"(
5909     bool GiveBool() { return true; }
5910 
5911     void target() {
5912       bool Foo = GiveBool();
5913       // [[p]]
5914     }
5915   )";
5916   runDataflow(
5917       Code,
5918       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5919          ASTContext &ASTCtx) {
5920         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5921         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5922 
5923         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5924         ASSERT_THAT(FooDecl, NotNull());
5925 
5926         auto &FooVal = getFormula(*FooDecl, Env);
5927         EXPECT_TRUE(Env.proves(FooVal));
5928       },
5929       {BuiltinOptions{ContextSensitiveOptions{}}});
5930 }
5931 
5932 TEST(TransferTest, ContextSensitiveReturnFalse) {
5933   std::string Code = R"(
5934     bool GiveBool() { return false; }
5935 
5936     void target() {
5937       bool Foo = GiveBool();
5938       // [[p]]
5939     }
5940   )";
5941   runDataflow(
5942       Code,
5943       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5944          ASTContext &ASTCtx) {
5945         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5946         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5947 
5948         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5949         ASSERT_THAT(FooDecl, NotNull());
5950 
5951         auto &FooVal = getFormula(*FooDecl, Env);
5952         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5953       },
5954       {BuiltinOptions{ContextSensitiveOptions{}}});
5955 }
5956 
5957 TEST(TransferTest, ContextSensitiveReturnArg) {
5958   std::string Code = R"(
5959     bool GiveBool();
5960     bool GiveBack(bool Arg) { return Arg; }
5961 
5962     void target() {
5963       bool Foo = GiveBool();
5964       bool Bar = GiveBack(Foo);
5965       bool Baz = Foo == Bar;
5966       // [[p]]
5967     }
5968   )";
5969   runDataflow(
5970       Code,
5971       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5972          ASTContext &ASTCtx) {
5973         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5974         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5975 
5976         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5977         ASSERT_THAT(BazDecl, NotNull());
5978 
5979         auto &BazVal = getFormula(*BazDecl, Env);
5980         EXPECT_TRUE(Env.proves(BazVal));
5981       },
5982       {BuiltinOptions{ContextSensitiveOptions{}}});
5983 }
5984 
5985 TEST(TransferTest, ContextSensitiveReturnInt) {
5986   std::string Code = R"(
5987     int identity(int x) { return x; }
5988 
5989     void target() {
5990       int y = identity(42);
5991       // [[p]]
5992     }
5993   )";
5994   runDataflow(
5995       Code,
5996       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5997          ASTContext &ASTCtx) {
5998         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5999         // This just tests that the analysis doesn't crash.
6000       },
6001       {BuiltinOptions{ContextSensitiveOptions{}}});
6002 }
6003 
6004 TEST(TransferTest, ContextSensitiveReturnRecord) {
6005   std::string Code = R"(
6006     struct S {
6007       bool B;
6008     };
6009 
6010     S makeS(bool BVal) { return {BVal}; }
6011 
6012     void target() {
6013       S FalseS = makeS(false);
6014       S TrueS = makeS(true);
6015       // [[p]]
6016     }
6017   )";
6018   runDataflow(
6019       Code,
6020       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6021          ASTContext &ASTCtx) {
6022         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6023 
6024         auto &FalseSLoc =
6025             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "FalseS");
6026         auto &TrueSLoc =
6027             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "TrueS");
6028 
6029         EXPECT_EQ(getFieldValue(&FalseSLoc, "B", ASTCtx, Env),
6030                   &Env.getBoolLiteralValue(false));
6031         EXPECT_EQ(getFieldValue(&TrueSLoc, "B", ASTCtx, Env),
6032                   &Env.getBoolLiteralValue(true));
6033       },
6034       {BuiltinOptions{ContextSensitiveOptions{}}});
6035 }
6036 
6037 TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {
6038   std::string Code = R"(
6039     struct S {
6040       S() { self = this; }
6041       S *self;
6042     };
6043 
6044     S makeS() {
6045       // RVO guarantees that this will be constructed directly into `MyS`.
6046       return S();
6047     }
6048 
6049     void target() {
6050       S MyS = makeS();
6051       // [[p]]
6052     }
6053   )";
6054   runDataflow(
6055       Code,
6056       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6057          ASTContext &ASTCtx) {
6058         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6059 
6060         auto &MySLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MyS");
6061 
6062         auto *SelfVal =
6063             cast<PointerValue>(getFieldValue(&MySLoc, "self", ASTCtx, Env));
6064         EXPECT_EQ(&SelfVal->getPointeeLoc(), &MySLoc);
6065       },
6066       {BuiltinOptions{ContextSensitiveOptions{}}});
6067 }
6068 
6069 TEST(TransferTest, ContextSensitiveMethodLiteral) {
6070   std::string Code = R"(
6071     class MyClass {
6072     public:
6073       bool giveBool() { return true; }
6074     };
6075 
6076     void target() {
6077       MyClass MyObj;
6078       bool Foo = MyObj.giveBool();
6079       // [[p]]
6080     }
6081   )";
6082   runDataflow(
6083       Code,
6084       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6085          ASTContext &ASTCtx) {
6086         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6087         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6088 
6089         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6090         ASSERT_THAT(FooDecl, NotNull());
6091 
6092         auto &FooVal = getFormula(*FooDecl, Env);
6093         EXPECT_TRUE(Env.proves(FooVal));
6094       },
6095       {BuiltinOptions{ContextSensitiveOptions{}}});
6096 }
6097 
6098 TEST(TransferTest, ContextSensitiveMethodGetter) {
6099   std::string Code = R"(
6100     class MyClass {
6101     public:
6102       bool getField() { return Field; }
6103 
6104       bool Field;
6105     };
6106 
6107     void target() {
6108       MyClass MyObj;
6109       MyObj.Field = true;
6110       bool Foo = MyObj.getField();
6111       // [[p]]
6112     }
6113   )";
6114   runDataflow(
6115       Code,
6116       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6117          ASTContext &ASTCtx) {
6118         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6119         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6120 
6121         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6122         ASSERT_THAT(FooDecl, NotNull());
6123 
6124         auto &FooVal = getFormula(*FooDecl, Env);
6125         EXPECT_TRUE(Env.proves(FooVal));
6126       },
6127       {BuiltinOptions{ContextSensitiveOptions{}}});
6128 }
6129 
6130 TEST(TransferTest, ContextSensitiveMethodSetter) {
6131   std::string Code = R"(
6132     class MyClass {
6133     public:
6134       void setField(bool Val) { Field = Val; }
6135 
6136       bool Field;
6137     };
6138 
6139     void target() {
6140       MyClass MyObj;
6141       MyObj.setField(true);
6142       bool Foo = MyObj.Field;
6143       // [[p]]
6144     }
6145   )";
6146   runDataflow(
6147       Code,
6148       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6149          ASTContext &ASTCtx) {
6150         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6151         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6152 
6153         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6154         ASSERT_THAT(FooDecl, NotNull());
6155 
6156         auto &FooVal = getFormula(*FooDecl, Env);
6157         EXPECT_TRUE(Env.proves(FooVal));
6158       },
6159       {BuiltinOptions{ContextSensitiveOptions{}}});
6160 }
6161 
6162 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
6163   std::string Code = R"(
6164     class MyClass {
6165     public:
6166       bool getField() { return Field; }
6167       void setField(bool Val) { Field = Val; }
6168 
6169     private:
6170       bool Field;
6171     };
6172 
6173     void target() {
6174       MyClass MyObj;
6175       MyObj.setField(true);
6176       bool Foo = MyObj.getField();
6177       // [[p]]
6178     }
6179   )";
6180   runDataflow(
6181       Code,
6182       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6183          ASTContext &ASTCtx) {
6184         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6185         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6186 
6187         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6188         ASSERT_THAT(FooDecl, NotNull());
6189 
6190         auto &FooVal = getFormula(*FooDecl, Env);
6191         EXPECT_TRUE(Env.proves(FooVal));
6192       },
6193       {BuiltinOptions{ContextSensitiveOptions{}}});
6194 }
6195 
6196 
6197 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
6198   std::string Code = R"(
6199     class MyClass {
6200     public:
6201       void Inner() { MyField = true; }
6202       void Outer() { Inner(); }
6203 
6204       bool MyField;
6205     };
6206 
6207     void target() {
6208       MyClass MyObj;
6209       MyObj.Outer();
6210       bool Foo = MyObj.MyField;
6211       // [[p]]
6212     }
6213   )";
6214   runDataflow(
6215       Code,
6216       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6217          ASTContext &ASTCtx) {
6218         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6219         ;
6220         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6221 
6222         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6223         ASSERT_THAT(FooDecl, NotNull());
6224 
6225         auto &FooVal = getFormula(*FooDecl, Env);
6226         EXPECT_TRUE(Env.proves(FooVal));
6227       },
6228       {BuiltinOptions{ContextSensitiveOptions{}}});
6229 }
6230 
6231 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
6232   std::string Code = R"(
6233     class MyClass {
6234     public:
6235       bool Inner() { return MyField; }
6236       bool Outer() { return Inner(); }
6237 
6238       bool MyField;
6239     };
6240 
6241     void target() {
6242       MyClass MyObj;
6243       MyObj.MyField = true;
6244       bool Foo = MyObj.Outer();
6245       // [[p]]
6246     }
6247   )";
6248   runDataflow(
6249       Code,
6250       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6251          ASTContext &ASTCtx) {
6252         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6253         ;
6254         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6255 
6256         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6257         ASSERT_THAT(FooDecl, NotNull());
6258 
6259         auto &FooVal = getFormula(*FooDecl, Env);
6260         EXPECT_TRUE(Env.proves(FooVal));
6261       },
6262       {BuiltinOptions{ContextSensitiveOptions{}}});
6263 }
6264 
6265 TEST(TransferTest, ContextSensitiveConstructorBody) {
6266   std::string Code = R"(
6267     class MyClass {
6268     public:
6269       MyClass() { MyField = true; }
6270 
6271       bool MyField;
6272     };
6273 
6274     void target() {
6275       MyClass MyObj;
6276       bool Foo = MyObj.MyField;
6277       // [[p]]
6278     }
6279   )";
6280   runDataflow(
6281       Code,
6282       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6283          ASTContext &ASTCtx) {
6284         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6285         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6286 
6287         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6288         ASSERT_THAT(FooDecl, NotNull());
6289 
6290         auto &FooVal = getFormula(*FooDecl, Env);
6291         EXPECT_TRUE(Env.proves(FooVal));
6292       },
6293       {BuiltinOptions{ContextSensitiveOptions{}}});
6294 }
6295 
6296 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
6297   std::string Code = R"(
6298     class MyClass {
6299     public:
6300       MyClass() : MyField(true) {}
6301 
6302       bool MyField;
6303     };
6304 
6305     void target() {
6306       MyClass MyObj;
6307       bool Foo = MyObj.MyField;
6308       // [[p]]
6309     }
6310   )";
6311   runDataflow(
6312       Code,
6313       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6314          ASTContext &ASTCtx) {
6315         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6316         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6317 
6318         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6319         ASSERT_THAT(FooDecl, NotNull());
6320 
6321         auto &FooVal = getFormula(*FooDecl, Env);
6322         EXPECT_TRUE(Env.proves(FooVal));
6323       },
6324       {BuiltinOptions{ContextSensitiveOptions{}}});
6325 }
6326 
6327 TEST(TransferTest, ContextSensitiveConstructorDefault) {
6328   std::string Code = R"(
6329     class MyClass {
6330     public:
6331       MyClass() = default;
6332 
6333       bool MyField = true;
6334     };
6335 
6336     void target() {
6337       MyClass MyObj;
6338       bool Foo = MyObj.MyField;
6339       // [[p]]
6340     }
6341   )";
6342   runDataflow(
6343       Code,
6344       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6345          ASTContext &ASTCtx) {
6346         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6347         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6348 
6349         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6350         ASSERT_THAT(FooDecl, NotNull());
6351 
6352         auto &FooVal = getFormula(*FooDecl, Env);
6353         EXPECT_TRUE(Env.proves(FooVal));
6354       },
6355       {BuiltinOptions{ContextSensitiveOptions{}}});
6356 }
6357 
6358 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
6359   // Test that the `this` pointer seen in the constructor has the same value
6360   // as the address of the variable the object is constructed into.
6361   std::string Code = R"(
6362     class MyClass {
6363     public:
6364       MyClass() : Self(this) {}
6365       MyClass *Self;
6366     };
6367 
6368     void target() {
6369       MyClass MyObj;
6370       MyClass *SelfPtr = MyObj.Self;
6371       // [[p]]
6372     }
6373   )";
6374   runDataflow(
6375       Code,
6376       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6377          ASTContext &ASTCtx) {
6378         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6379 
6380         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
6381         ASSERT_THAT(MyObjDecl, NotNull());
6382 
6383         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
6384         ASSERT_THAT(SelfDecl, NotNull());
6385 
6386         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6387         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
6388         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
6389       },
6390       {BuiltinOptions{ContextSensitiveOptions{}}});
6391 }
6392 
6393 TEST(TransferTest, UnnamedBitfieldInitializer) {
6394   std::string Code = R"(
6395     struct B {};
6396     struct A {
6397       unsigned a;
6398       unsigned : 4;
6399       unsigned c;
6400       B b;
6401     };
6402     void target() {
6403       A a = {};
6404       A test = a;
6405       (void)test.c;
6406     }
6407   )";
6408   runDataflow(
6409       Code,
6410       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6411          ASTContext &ASTCtx) {
6412         // This doesn't need a body because this test was crashing the framework
6413         // before handling correctly Unnamed bitfields in `InitListExpr`.
6414       });
6415 }
6416 
6417 // Repro for a crash that used to occur with chained short-circuiting logical
6418 // operators.
6419 TEST(TransferTest, ChainedLogicalOps) {
6420   std::string Code = R"(
6421     bool target() {
6422       bool b = true || false || false || false;
6423       // [[p]]
6424       return b;
6425     }
6426   )";
6427   runDataflow(
6428       Code,
6429       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6430          ASTContext &ASTCtx) {
6431         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6432         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6433         EXPECT_TRUE(Env.proves(B));
6434       });
6435 }
6436 
6437 // Repro for a crash that used to occur when we call a `noreturn` function
6438 // within one of the operands of a `&&` or `||` operator.
6439 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
6440   std::string Code = R"(
6441     __attribute__((noreturn)) int doesnt_return();
6442     bool some_condition();
6443     void target(bool b1, bool b2) {
6444       // Neither of these should crash. In addition, if we don't terminate the
6445       // program, we know that the operators need to trigger the short-circuit
6446       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
6447       // will be true.
6448       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
6449       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
6450 
6451       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
6452       // entire expression unreachable. So we know that in both of the following
6453       // cases, if `target()` terminates, the `else` branch was taken.
6454       bool NoreturnOnLhsMakesAndUnreachable = false;
6455       if (some_condition())
6456          doesnt_return() > 0 && some_condition();
6457       else
6458          NoreturnOnLhsMakesAndUnreachable = true;
6459 
6460       bool NoreturnOnLhsMakesOrUnreachable = false;
6461       if (some_condition())
6462          doesnt_return() > 0 || some_condition();
6463       else
6464          NoreturnOnLhsMakesOrUnreachable = true;
6465 
6466       // [[p]]
6467     }
6468   )";
6469   runDataflow(
6470       Code,
6471       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6472          ASTContext &ASTCtx) {
6473         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6474         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6475         auto &A = Env.arena();
6476 
6477         // Check that [[p]] is reachable with a non-false flow condition.
6478         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
6479 
6480         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
6481         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
6482 
6483         auto &NoreturnOnRhsOfAnd =
6484             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
6485         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
6486 
6487         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
6488         EXPECT_TRUE(Env.proves(B2));
6489 
6490         auto &NoreturnOnRhsOfOr =
6491             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
6492                 .formula();
6493         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
6494 
6495         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
6496             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
6497         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
6498 
6499         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
6500             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
6501         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
6502       });
6503 }
6504 
6505 TEST(TransferTest, NewExpressions) {
6506   std::string Code = R"(
6507     void target() {
6508       int *p = new int(42);
6509       // [[after_new]]
6510     }
6511   )";
6512   runDataflow(
6513       Code,
6514       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6515          ASTContext &ASTCtx) {
6516         const Environment &Env =
6517             getEnvironmentAtAnnotation(Results, "after_new");
6518 
6519         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6520 
6521         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
6522       });
6523 }
6524 
6525 TEST(TransferTest, NewExpressions_Structs) {
6526   std::string Code = R"(
6527     struct Inner {
6528       int InnerField;
6529     };
6530 
6531     struct Outer {
6532       Inner OuterField;
6533     };
6534 
6535     void target() {
6536       Outer *p = new Outer;
6537       // Access the fields to make sure the analysis actually generates children
6538       // for them in the `RecordStorageLocation` and `RecordValue`.
6539       p->OuterField.InnerField;
6540       // [[after_new]]
6541     }
6542   )";
6543   runDataflow(
6544       Code,
6545       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6546          ASTContext &ASTCtx) {
6547         const Environment &Env =
6548             getEnvironmentAtAnnotation(Results, "after_new");
6549 
6550         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
6551         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
6552 
6553         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6554 
6555         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
6556         auto &OuterFieldLoc =
6557             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
6558         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
6559 
6560         // Values for the struct and all fields exist after the new.
6561         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
6562         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
6563         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
6564       });
6565 }
6566 
6567 TEST(TransferTest, FunctionToPointerDecayHasValue) {
6568   std::string Code = R"(
6569     struct A { static void static_member_func(); };
6570     void target() {
6571       // To check that we're treating function-to-pointer decay correctly,
6572       // create two pointers, then verify they refer to the same storage
6573       // location.
6574       // We need to do the test this way because even if an initializer (in this
6575       // case, the function-to-pointer decay) does not create a value, we still
6576       // create a value for the variable.
6577       void (*non_member_p1)() = target;
6578       void (*non_member_p2)() = target;
6579 
6580       // Do the same thing but for a static member function.
6581       void (*member_p1)() = A::static_member_func;
6582       void (*member_p2)() = A::static_member_func;
6583       // [[p]]
6584     }
6585   )";
6586   runDataflow(
6587       Code,
6588       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6589          ASTContext &ASTCtx) {
6590         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6591 
6592         auto &NonMemberP1 =
6593             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
6594         auto &NonMemberP2 =
6595             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
6596         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
6597 
6598         auto &MemberP1 =
6599             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
6600         auto &MemberP2 =
6601             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
6602         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
6603       });
6604 }
6605 
6606 // Check that a builtin function is not associated with a value. (It's only
6607 // possible to call builtin functions directly, not take their address.)
6608 TEST(TransferTest, BuiltinFunctionModeled) {
6609   std::string Code = R"(
6610     void target() {
6611       __builtin_expect(0, 0);
6612       // [[p]]
6613     }
6614   )";
6615   runDataflow(
6616       Code,
6617       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6618          ASTContext &ASTCtx) {
6619         using ast_matchers::selectFirst;
6620         using ast_matchers::match;
6621         using ast_matchers::traverse;
6622         using ast_matchers::implicitCastExpr;
6623         using ast_matchers::hasCastKind;
6624 
6625         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6626 
6627         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
6628             "implicit_cast",
6629             match(traverse(TK_AsIs,
6630                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
6631                                .bind("implicit_cast")),
6632                   ASTCtx));
6633 
6634         ASSERT_THAT(ImplicitCast, NotNull());
6635         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
6636       });
6637 }
6638 
6639 // Check that a callee of a member operator call is modeled as a `PointerValue`.
6640 // Member operator calls are unusual in that their callee is a pointer that
6641 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
6642 // member functions, the callee is a `MemberExpr` (which does not have pointer
6643 // type).
6644 // We want to make sure that we produce a pointer value for the callee in this
6645 // specific scenario and that its storage location is durable (for convergence).
6646 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
6647   std::string Code = R"(
6648     struct S {
6649       bool operator!=(S s);
6650     };
6651     void target() {
6652       S s;
6653       (void)(s != s);
6654       (void)(s != s);
6655       // [[p]]
6656     }
6657   )";
6658   runDataflow(
6659       Code,
6660       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6661          ASTContext &ASTCtx) {
6662         using ast_matchers::selectFirst;
6663         using ast_matchers::match;
6664         using ast_matchers::traverse;
6665         using ast_matchers::cxxOperatorCallExpr;
6666 
6667         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6668 
6669         auto Matches = match(
6670             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
6671 
6672         ASSERT_EQ(Matches.size(), 2UL);
6673 
6674         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
6675         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
6676 
6677         ASSERT_THAT(Call1, NotNull());
6678         ASSERT_THAT(Call2, NotNull());
6679 
6680         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
6681                   CK_FunctionToPointerDecay);
6682         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
6683                   CK_FunctionToPointerDecay);
6684 
6685         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
6686         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
6687 
6688         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
6689       });
6690 }
6691 
6692 // Check that fields of anonymous records are modeled.
6693 TEST(TransferTest, AnonymousStruct) {
6694   std::string Code = R"(
6695     struct S {
6696       struct {
6697         bool b;
6698       };
6699     };
6700     void target() {
6701       S s;
6702       s.b = true;
6703       // [[p]]
6704     }
6705   )";
6706   runDataflow(
6707       Code,
6708       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6709          ASTContext &ASTCtx) {
6710         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6711         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
6712         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6713         const IndirectFieldDecl *IndirectField =
6714             findIndirectFieldDecl(ASTCtx, "b");
6715 
6716         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
6717         auto &AnonStruct = *cast<RecordStorageLocation>(
6718             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
6719 
6720         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6721         ASSERT_TRUE(Env.proves(B->formula()));
6722       });
6723 }
6724 
6725 TEST(TransferTest, AnonymousStructWithInitializer) {
6726   std::string Code = R"(
6727     struct target {
6728       target() {
6729         (void)0;
6730         // [[p]]
6731       }
6732       struct {
6733         bool b = true;
6734       };
6735     };
6736   )";
6737   runDataflow(
6738       Code,
6739       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6740          ASTContext &ASTCtx) {
6741         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6742         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6743         const IndirectFieldDecl *IndirectField =
6744             findIndirectFieldDecl(ASTCtx, "b");
6745 
6746         auto *ThisLoc =
6747             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6748         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6749             *cast<ValueDecl>(IndirectField->chain().front())));
6750 
6751         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6752         ASSERT_TRUE(Env.proves(B->formula()));
6753       });
6754 }
6755 
6756 TEST(TransferTest, AnonymousStructWithReferenceField) {
6757   std::string Code = R"(
6758     int global_i = 0;
6759     struct target {
6760       target() {
6761         (void)0;
6762         // [[p]]
6763       }
6764       struct {
6765         int &i = global_i;
6766       };
6767     };
6768   )";
6769   runDataflow(
6770       Code,
6771       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6772          ASTContext &ASTCtx) {
6773         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6774         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6775         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6776         const IndirectFieldDecl *IndirectField =
6777             findIndirectFieldDecl(ASTCtx, "i");
6778 
6779         auto *ThisLoc =
6780             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6781         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6782             *cast<ValueDecl>(IndirectField->chain().front())));
6783 
6784         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6785                   Env.getStorageLocation(*GlobalIDecl));
6786       });
6787 }
6788 
6789 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6790   // This is a crash repro.
6791   // `false` block may not have been processed when we try to evaluate the `||`
6792   // after visiting `true`, because it is not necessary (and therefore the edge
6793   // is marked unreachable). Trying to get the analysis state via
6794   // `getEnvironment` for the subexpression still should not crash.
6795   std::string Code = R"(
6796     int target(int i) {
6797       if ((i < 0 && true) || false) {
6798         return 0;
6799       }
6800       return 0;
6801     }
6802   )";
6803   runDataflow(
6804       Code,
6805       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6806          ASTContext &ASTCtx) {});
6807 }
6808 
6809 TEST(TransferTest, LambdaCaptureByCopy) {
6810   std::string Code = R"(
6811     void target(int Foo, int Bar) {
6812       [Foo]() {
6813         (void)0;
6814         // [[p]]
6815       }();
6816     }
6817   )";
6818   runDataflowOnLambda(
6819       Code,
6820       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6821          ASTContext &ASTCtx) {
6822         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6823         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6824 
6825         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6826         ASSERT_THAT(FooDecl, NotNull());
6827 
6828         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6829         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6830 
6831         const Value *FooVal = Env.getValue(*FooLoc);
6832         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6833 
6834         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6835         ASSERT_THAT(BarDecl, NotNull());
6836 
6837         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6838         EXPECT_THAT(BarLoc, IsNull());
6839       });
6840 }
6841 
6842 TEST(TransferTest, LambdaCaptureByReference) {
6843   std::string Code = R"(
6844     void target(int Foo, int Bar) {
6845       [&Foo]() {
6846         (void)0;
6847         // [[p]]
6848       }();
6849     }
6850   )";
6851   runDataflowOnLambda(
6852       Code,
6853       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6854          ASTContext &ASTCtx) {
6855         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6856         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6857 
6858         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6859         ASSERT_THAT(FooDecl, NotNull());
6860 
6861         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6862         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6863 
6864         const Value *FooVal = Env.getValue(*FooLoc);
6865         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6866 
6867         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6868         ASSERT_THAT(BarDecl, NotNull());
6869 
6870         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6871         EXPECT_THAT(BarLoc, IsNull());
6872       });
6873 }
6874 
6875 TEST(TransferTest, LambdaCaptureWithInitializer) {
6876   std::string Code = R"(
6877     void target(int Bar) {
6878       [Foo=Bar]() {
6879         (void)0;
6880         // [[p]]
6881       }();
6882     }
6883   )";
6884   runDataflowOnLambda(
6885       Code,
6886       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6887          ASTContext &ASTCtx) {
6888         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6889         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6890 
6891         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6892         ASSERT_THAT(FooDecl, NotNull());
6893 
6894         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6895         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6896 
6897         const Value *FooVal = Env.getValue(*FooLoc);
6898         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6899 
6900         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6901         ASSERT_THAT(BarDecl, NotNull());
6902 
6903         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6904         EXPECT_THAT(BarLoc, IsNull());
6905       });
6906 }
6907 
6908 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
6909   std::string Code = R"(
6910     void target(int Foo, int Bar) {
6911       [=]() {
6912         Foo;
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         // There is no storage location for `Bar` because it isn't used in the
6937         // body of the lambda.
6938         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6939         EXPECT_THAT(BarLoc, IsNull());
6940       });
6941 }
6942 
6943 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
6944   std::string Code = R"(
6945     void target(int Foo, int Bar) {
6946       [&]() {
6947         Foo;
6948         // [[p]]
6949       }();
6950     }
6951   )";
6952   runDataflowOnLambda(
6953       Code,
6954       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6955          ASTContext &ASTCtx) {
6956         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6957         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6958 
6959         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6960         ASSERT_THAT(FooDecl, NotNull());
6961 
6962         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6963         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6964 
6965         const Value *FooVal = Env.getValue(*FooLoc);
6966         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6967 
6968         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6969         ASSERT_THAT(BarDecl, NotNull());
6970 
6971         // There is no storage location for `Bar` because it isn't used in the
6972         // body of the lambda.
6973         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6974         EXPECT_THAT(BarLoc, IsNull());
6975       });
6976 }
6977 
6978 TEST(TransferTest, LambdaCaptureThis) {
6979   std::string Code = R"(
6980     struct Bar {
6981       int Foo;
6982 
6983       void target() {
6984         [this]() {
6985           Foo;
6986           // [[p]]
6987         }();
6988       }
6989     };
6990   )";
6991   runDataflowOnLambda(
6992       Code,
6993       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6994          ASTContext &ASTCtx) {
6995         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6996         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6997 
6998         const RecordStorageLocation *ThisPointeeLoc =
6999             Env.getThisPointeeStorageLocation();
7000         ASSERT_THAT(ThisPointeeLoc, NotNull());
7001 
7002         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7003         ASSERT_THAT(FooDecl, NotNull());
7004 
7005         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
7006         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7007 
7008         const Value *FooVal = Env.getValue(*FooLoc);
7009         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7010       });
7011 }
7012 
7013 // This test verifies correct modeling of a relational dependency that goes
7014 // through unmodeled functions (the simple `cond()` in this case).
7015 TEST(TransferTest, ConditionalRelation) {
7016   std::string Code = R"(
7017     bool cond();
7018     void target() {
7019        bool a = true;
7020        bool b = true;
7021        if (cond()) {
7022          a = false;
7023          if (cond()) {
7024            b = false;
7025          }
7026        }
7027        (void)0;
7028        // [[p]]
7029     }
7030  )";
7031   runDataflow(
7032       Code,
7033       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7034          ASTContext &ASTCtx) {
7035         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7036         auto &A = Env.arena();
7037         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
7038         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
7039 
7040         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
7041       });
7042 }
7043 
7044 } // namespace
7045