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