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