xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 762cb1d377362daff234ac5172c2c1db4918f6d3)
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/StorageLocation.h"
17 #include "clang/Analysis/FlowSensitive/Value.h"
18 #include "clang/Basic/LangStandard.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/Casting.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 using BuiltinOptions = DataflowAnalysisContext::Options;
42 
43 template <typename Matcher>
44 llvm::Error
45 runDataflowReturnError(llvm::StringRef Code, Matcher Match,
46                        DataflowAnalysisOptions Options,
47                        LangStandard::Kind Std = LangStandard::lang_cxx17,
48                        llvm::StringRef TargetFun = "target") {
49   using ast_matchers::hasName;
50   llvm::SmallVector<std::string, 3> ASTBuildArgs = {
51       // -fnodelayed-template-parsing is the default everywhere but on Windows.
52       // Set it explicitly so that tests behave the same on Windows as on other
53       // platforms.
54       "-fsyntax-only", "-fno-delayed-template-parsing",
55       "-std=" +
56           std::string(LangStandard::getLangStandardForKind(Std).getName())};
57   AnalysisInputs<NoopAnalysis> AI(
58       Code, hasName(TargetFun),
59       [UseBuiltinModel = Options.BuiltinOpts.has_value()](ASTContext &C,
60                                                           Environment &Env) {
61         return NoopAnalysis(
62             C,
63             DataflowAnalysisOptions{
64                 UseBuiltinModel ? Env.getDataflowAnalysisContext().getOptions()
65                                 : std::optional<BuiltinOptions>()});
66       });
67   AI.ASTBuildArgs = ASTBuildArgs;
68   if (Options.BuiltinOpts)
69     AI.BuiltinOptions = *Options.BuiltinOpts;
70   return checkDataflow<NoopAnalysis>(
71       std::move(AI),
72       /*VerifyResults=*/
73       [&Match](
74           const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
75           const AnalysisOutputs &AO) { Match(Results, AO.ASTCtx); });
76 }
77 
78 template <typename Matcher>
79 void runDataflow(llvm::StringRef Code, Matcher Match,
80                  DataflowAnalysisOptions Options,
81                  LangStandard::Kind Std = LangStandard::lang_cxx17,
82                  llvm::StringRef TargetFun = "target") {
83   ASSERT_THAT_ERROR(
84       runDataflowReturnError(Code, Match, Options, Std, TargetFun),
85       llvm::Succeeded());
86 }
87 
88 template <typename Matcher>
89 void runDataflow(llvm::StringRef Code, Matcher Match,
90                  LangStandard::Kind Std = LangStandard::lang_cxx17,
91                  bool ApplyBuiltinTransfer = true,
92                  llvm::StringRef TargetFun = "target") {
93   runDataflow(Code, std::move(Match),
94               {ApplyBuiltinTransfer ? BuiltinOptions{}
95                                     : std::optional<BuiltinOptions>()},
96               Std, TargetFun);
97 }
98 
99 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
100   std::string Code = R"(
101     void target() {
102       int Foo;
103       // [[p]]
104     }
105   )";
106   runDataflow(
107       Code,
108       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
109          ASTContext &ASTCtx) {
110         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
111         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
112 
113         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
114         ASSERT_THAT(FooDecl, NotNull());
115 
116         EXPECT_EQ(Env.getStorageLocation(*FooDecl), nullptr);
117       },
118       LangStandard::lang_cxx17,
119       /*ApplyBuiltinTransfer=*/false);
120 }
121 
122 TEST(TransferTest, BoolVarDecl) {
123   std::string Code = R"(
124     void target() {
125       bool Foo;
126       // [[p]]
127     }
128   )";
129   runDataflow(
130       Code,
131       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
132          ASTContext &ASTCtx) {
133         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
134         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
135 
136         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
137         ASSERT_THAT(FooDecl, NotNull());
138 
139         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
140         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
141 
142         const Value *FooVal = Env.getValue(*FooLoc);
143         EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal));
144       });
145 }
146 
147 TEST(TransferTest, IntVarDecl) {
148   std::string Code = R"(
149     void target() {
150       int Foo;
151       // [[p]]
152     }
153   )";
154   runDataflow(
155       Code,
156       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
157          ASTContext &ASTCtx) {
158         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
159         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
160 
161         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
162         ASSERT_THAT(FooDecl, NotNull());
163 
164         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
165         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
166 
167         const Value *FooVal = Env.getValue(*FooLoc);
168         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
169       });
170 }
171 
172 TEST(TransferTest, StructIncomplete) {
173   std::string Code = R"(
174     struct A;
175 
176     void target() {
177       A* Foo;
178       // [[p]]
179     }
180   )";
181   runDataflow(
182       Code,
183       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
184          ASTContext &ASTCtx) {
185         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
186         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
187 
188         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
189         ASSERT_THAT(FooDecl, NotNull());
190         auto *FooValue = dyn_cast_or_null<PointerValue>(Env.getValue(*FooDecl));
191         ASSERT_THAT(FooValue, NotNull());
192 
193         EXPECT_TRUE(isa<AggregateStorageLocation>(FooValue->getPointeeLoc()));
194         auto *FooPointeeValue = Env.getValue(FooValue->getPointeeLoc());
195         ASSERT_THAT(FooPointeeValue, NotNull());
196         EXPECT_TRUE(isa<StructValue>(FooPointeeValue));
197       });
198 }
199 
200 // As a memory optimization, we prevent modeling fields nested below a certain
201 // level (currently, depth 3). This test verifies this lack of modeling. We also
202 // include a regression test for the case that the unmodeled field is a
203 // reference to a struct; previously, we crashed when accessing such a field.
204 TEST(TransferTest, StructFieldUnmodeled) {
205   std::string Code = R"(
206     struct S { int X; };
207     S GlobalS;
208     struct A { S &Unmodeled = GlobalS; };
209     struct B { A F3; };
210     struct C { B F2; };
211     struct D { C F1; };
212 
213     void target() {
214       D Bar;
215       A Foo = Bar.F1.F2.F3;
216       int Zab = Foo.Unmodeled.X;
217       // [[p]]
218     }
219   )";
220   runDataflow(
221       Code,
222       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
223          ASTContext &ASTCtx) {
224         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
225         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
226 
227         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
228         ASSERT_THAT(FooDecl, NotNull());
229         ASSERT_TRUE(FooDecl->getType()->isStructureType());
230         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
231 
232         FieldDecl *UnmodeledDecl = nullptr;
233         for (FieldDecl *Field : FooFields) {
234           if (Field->getNameAsString() == "Unmodeled") {
235             UnmodeledDecl = Field;
236           } else {
237             FAIL() << "Unexpected field: " << Field->getNameAsString();
238           }
239         }
240         ASSERT_THAT(UnmodeledDecl, NotNull());
241 
242         const auto *FooLoc =
243             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
244         const auto *UnmodeledLoc = &FooLoc->getChild(*UnmodeledDecl);
245         ASSERT_TRUE(isa<ScalarStorageLocation>(UnmodeledLoc));
246         ASSERT_THAT(Env.getValue(*UnmodeledLoc), IsNull());
247 
248         const ValueDecl *ZabDecl = findValueDecl(ASTCtx, "Zab");
249         ASSERT_THAT(ZabDecl, NotNull());
250         EXPECT_THAT(Env.getValue(*ZabDecl), NotNull());
251       });
252 }
253 
254 TEST(TransferTest, StructVarDecl) {
255   std::string Code = R"(
256     struct A {
257       int Bar;
258     };
259 
260     void target() {
261       A Foo;
262       (void)Foo.Bar;
263       // [[p]]
264     }
265   )";
266   runDataflow(
267       Code,
268       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
269          ASTContext &ASTCtx) {
270         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
271         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
272 
273         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
274         ASSERT_THAT(FooDecl, NotNull());
275 
276         ASSERT_TRUE(FooDecl->getType()->isStructureType());
277         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
278 
279         FieldDecl *BarDecl = nullptr;
280         for (FieldDecl *Field : FooFields) {
281           if (Field->getNameAsString() == "Bar") {
282             BarDecl = Field;
283           } else {
284             FAIL() << "Unexpected field: " << Field->getNameAsString();
285           }
286         }
287         ASSERT_THAT(BarDecl, NotNull());
288 
289         const auto *FooLoc =
290             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
291         const auto *BarLoc =
292             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
293 
294         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
295         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
296         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
297       });
298 }
299 
300 TEST(TransferTest, StructVarDeclWithInit) {
301   std::string Code = R"(
302     struct A {
303       int Bar;
304     };
305 
306     A Gen();
307 
308     void target() {
309       A Foo = Gen();
310       (void)Foo.Bar;
311       // [[p]]
312     }
313   )";
314   runDataflow(
315       Code,
316       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
317          ASTContext &ASTCtx) {
318         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
319         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
320 
321         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
322         ASSERT_THAT(FooDecl, NotNull());
323 
324         ASSERT_TRUE(FooDecl->getType()->isStructureType());
325         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
326 
327         FieldDecl *BarDecl = nullptr;
328         for (FieldDecl *Field : FooFields) {
329           if (Field->getNameAsString() == "Bar") {
330             BarDecl = Field;
331           } else {
332             FAIL() << "Unexpected field: " << Field->getNameAsString();
333           }
334         }
335         ASSERT_THAT(BarDecl, NotNull());
336 
337         const auto *FooLoc =
338             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
339         const auto *BarLoc =
340             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
341 
342         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
343         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
344         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
345       });
346 }
347 
348 TEST(TransferTest, ClassVarDecl) {
349   std::string Code = R"(
350     class A {
351      public:
352       int Bar;
353     };
354 
355     void target() {
356       A Foo;
357       (void)Foo.Bar;
358       // [[p]]
359     }
360   )";
361   runDataflow(
362       Code,
363       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
364          ASTContext &ASTCtx) {
365         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
366         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
367 
368         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
369         ASSERT_THAT(FooDecl, NotNull());
370 
371         ASSERT_TRUE(FooDecl->getType()->isClassType());
372         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
373 
374         FieldDecl *BarDecl = nullptr;
375         for (FieldDecl *Field : FooFields) {
376           if (Field->getNameAsString() == "Bar") {
377             BarDecl = Field;
378           } else {
379             FAIL() << "Unexpected field: " << Field->getNameAsString();
380           }
381         }
382         ASSERT_THAT(BarDecl, NotNull());
383 
384         const auto *FooLoc =
385             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
386         const auto *BarLoc =
387             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
388 
389         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
390         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
391         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
392       });
393 }
394 
395 TEST(TransferTest, ReferenceVarDecl) {
396   std::string Code = R"(
397     struct A {};
398 
399     A &getA();
400 
401     void target() {
402       A &Foo = getA();
403       // [[p]]
404     }
405   )";
406   runDataflow(
407       Code,
408       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
409          ASTContext &ASTCtx) {
410         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
411         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
412 
413         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
414         ASSERT_THAT(FooDecl, NotNull());
415 
416         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
417         ASSERT_TRUE(isa_and_nonnull<AggregateStorageLocation>(FooLoc));
418 
419         const Value *FooReferentVal = Env.getValue(*FooLoc);
420         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal));
421       });
422 }
423 
424 TEST(TransferTest, SelfReferentialReferenceVarDecl) {
425   std::string Code = R"(
426     struct A;
427 
428     struct B {};
429 
430     struct C {
431       A &FooRef;
432       A *FooPtr;
433       B &BazRef;
434       B *BazPtr;
435     };
436 
437     struct A {
438       C &Bar;
439     };
440 
441     A &getA();
442 
443     void target() {
444       A &Foo = getA();
445       (void)Foo.Bar.FooRef;
446       (void)Foo.Bar.FooPtr;
447       (void)Foo.Bar.BazRef;
448       (void)Foo.Bar.BazPtr;
449       // [[p]]
450     }
451   )";
452   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
453                            &Results,
454                        ASTContext &ASTCtx) {
455     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
456     const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
457 
458     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
459     ASSERT_THAT(FooDecl, NotNull());
460 
461     ASSERT_TRUE(FooDecl->getType()->isReferenceType());
462     ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType());
463     const auto FooFields =
464         FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
465 
466     FieldDecl *BarDecl = nullptr;
467     for (FieldDecl *Field : FooFields) {
468       if (Field->getNameAsString() == "Bar") {
469         BarDecl = Field;
470       } else {
471         FAIL() << "Unexpected field: " << Field->getNameAsString();
472       }
473     }
474     ASSERT_THAT(BarDecl, NotNull());
475 
476     ASSERT_TRUE(BarDecl->getType()->isReferenceType());
477     ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType());
478     const auto BarFields =
479         BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
480 
481     FieldDecl *FooRefDecl = nullptr;
482     FieldDecl *FooPtrDecl = nullptr;
483     FieldDecl *BazRefDecl = nullptr;
484     FieldDecl *BazPtrDecl = nullptr;
485     for (FieldDecl *Field : BarFields) {
486       if (Field->getNameAsString() == "FooRef") {
487         FooRefDecl = Field;
488       } else if (Field->getNameAsString() == "FooPtr") {
489         FooPtrDecl = Field;
490       } else if (Field->getNameAsString() == "BazRef") {
491         BazRefDecl = Field;
492       } else if (Field->getNameAsString() == "BazPtr") {
493         BazPtrDecl = Field;
494       } else {
495         FAIL() << "Unexpected field: " << Field->getNameAsString();
496       }
497     }
498     ASSERT_THAT(FooRefDecl, NotNull());
499     ASSERT_THAT(FooPtrDecl, NotNull());
500     ASSERT_THAT(BazRefDecl, NotNull());
501     ASSERT_THAT(BazPtrDecl, NotNull());
502 
503     const auto *FooLoc =
504         cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
505     const auto *FooReferentVal = cast<StructValue>(Env.getValue(*FooLoc));
506 
507     const auto *BarVal =
508         cast<ReferenceValue>(FooReferentVal->getChild(*BarDecl));
509     const auto *BarReferentVal =
510         cast<StructValue>(Env.getValue(BarVal->getReferentLoc()));
511 
512     const auto *FooRefVal =
513         cast<ReferenceValue>(BarReferentVal->getChild(*FooRefDecl));
514     const auto &FooReferentLoc =
515         cast<AggregateStorageLocation>(FooRefVal->getReferentLoc());
516     EXPECT_THAT(Env.getValue(FooReferentLoc), NotNull());
517     EXPECT_THAT(Env.getValue(FooReferentLoc.getChild(*BarDecl)), IsNull());
518 
519     const auto *FooPtrVal =
520         cast<PointerValue>(BarReferentVal->getChild(*FooPtrDecl));
521     const auto &FooPtrPointeeLoc =
522         cast<AggregateStorageLocation>(FooPtrVal->getPointeeLoc());
523     EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), NotNull());
524     EXPECT_THAT(Env.getValue(FooPtrPointeeLoc.getChild(*BarDecl)), IsNull());
525 
526     const auto *BazRefVal =
527         cast<ReferenceValue>(BarReferentVal->getChild(*BazRefDecl));
528     const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc();
529     EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull());
530 
531     const auto *BazPtrVal =
532         cast<PointerValue>(BarReferentVal->getChild(*BazPtrDecl));
533     const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
534     EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
535   });
536 }
537 
538 TEST(TransferTest, PointerVarDecl) {
539   std::string Code = R"(
540     struct A {};
541 
542     A *getA();
543 
544     void target() {
545       A *Foo = getA();
546       // [[p]]
547     }
548   )";
549   runDataflow(
550       Code,
551       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
552          ASTContext &ASTCtx) {
553         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
554         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
555 
556         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
557         ASSERT_THAT(FooDecl, NotNull());
558 
559         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
560         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
561 
562         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
563         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
564         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
565 
566         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
567         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
568       });
569 }
570 
571 TEST(TransferTest, SelfReferentialPointerVarDecl) {
572   std::string Code = R"(
573     struct A;
574 
575     struct B {};
576 
577     struct C {
578       A &FooRef;
579       A *FooPtr;
580       B &BazRef;
581       B *BazPtr;
582     };
583 
584     struct A {
585       C *Bar;
586     };
587 
588     A *getA();
589 
590     void target() {
591       A *Foo = getA();
592       (void)Foo->Bar->FooRef;
593       (void)Foo->Bar->FooPtr;
594       (void)Foo->Bar->BazRef;
595       (void)Foo->Bar->BazPtr;
596       // [[p]]
597     }
598   )";
599   runDataflow(
600       Code,
601       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
602          ASTContext &ASTCtx) {
603         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
604         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
605 
606         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
607         ASSERT_THAT(FooDecl, NotNull());
608 
609         ASSERT_TRUE(FooDecl->getType()->isPointerType());
610         ASSERT_TRUE(FooDecl->getType()
611                         ->getAs<PointerType>()
612                         ->getPointeeType()
613                         ->isStructureType());
614         const auto FooFields = FooDecl->getType()
615                                    ->getAs<PointerType>()
616                                    ->getPointeeType()
617                                    ->getAsRecordDecl()
618                                    ->fields();
619 
620         FieldDecl *BarDecl = nullptr;
621         for (FieldDecl *Field : FooFields) {
622           if (Field->getNameAsString() == "Bar") {
623             BarDecl = Field;
624           } else {
625             FAIL() << "Unexpected field: " << Field->getNameAsString();
626           }
627         }
628         ASSERT_THAT(BarDecl, NotNull());
629 
630         ASSERT_TRUE(BarDecl->getType()->isPointerType());
631         ASSERT_TRUE(BarDecl->getType()
632                         ->getAs<PointerType>()
633                         ->getPointeeType()
634                         ->isStructureType());
635         const auto BarFields = BarDecl->getType()
636                                    ->getAs<PointerType>()
637                                    ->getPointeeType()
638                                    ->getAsRecordDecl()
639                                    ->fields();
640 
641         FieldDecl *FooRefDecl = nullptr;
642         FieldDecl *FooPtrDecl = nullptr;
643         FieldDecl *BazRefDecl = nullptr;
644         FieldDecl *BazPtrDecl = nullptr;
645         for (FieldDecl *Field : BarFields) {
646           if (Field->getNameAsString() == "FooRef") {
647             FooRefDecl = Field;
648           } else if (Field->getNameAsString() == "FooPtr") {
649             FooPtrDecl = Field;
650           } else if (Field->getNameAsString() == "BazRef") {
651             BazRefDecl = Field;
652           } else if (Field->getNameAsString() == "BazPtr") {
653             BazPtrDecl = Field;
654           } else {
655             FAIL() << "Unexpected field: " << Field->getNameAsString();
656           }
657         }
658         ASSERT_THAT(FooRefDecl, NotNull());
659         ASSERT_THAT(FooPtrDecl, NotNull());
660         ASSERT_THAT(BazRefDecl, NotNull());
661         ASSERT_THAT(BazPtrDecl, NotNull());
662 
663         const auto *FooLoc =
664             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
665         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
666         const auto *FooPointeeVal =
667             cast<StructValue>(Env.getValue(FooVal->getPointeeLoc()));
668 
669         const auto *BarVal =
670             cast<PointerValue>(FooPointeeVal->getChild(*BarDecl));
671         const auto *BarPointeeVal =
672             cast<StructValue>(Env.getValue(BarVal->getPointeeLoc()));
673 
674         const auto *FooRefVal =
675             cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl));
676         const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc();
677         EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull());
678 
679         const auto *FooPtrVal =
680             cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl));
681         const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc();
682         EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
683 
684         const auto *BazRefVal =
685             cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl));
686         const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc();
687         EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull());
688 
689         const auto *BazPtrVal =
690             cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl));
691         const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
692         EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
693       });
694 }
695 
696 TEST(TransferTest, MultipleVarsDecl) {
697   std::string Code = R"(
698     void target() {
699       int Foo, Bar;
700       (void)0;
701       // [[p]]
702     }
703   )";
704   runDataflow(
705       Code,
706       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
707          ASTContext &ASTCtx) {
708         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
709         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
710 
711         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
712         ASSERT_THAT(FooDecl, NotNull());
713 
714         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
715         ASSERT_THAT(BarDecl, NotNull());
716 
717         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
718         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
719 
720         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
721         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
722 
723         const Value *FooVal = Env.getValue(*FooLoc);
724         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
725 
726         const Value *BarVal = Env.getValue(*BarLoc);
727         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
728       });
729 }
730 
731 TEST(TransferTest, JoinVarDecl) {
732   std::string Code = R"(
733     void target(bool B) {
734       int Foo;
735       // [[p1]]
736       if (B) {
737         int Bar;
738         // [[p2]]
739       } else {
740         int Baz;
741         // [[p3]]
742       }
743       (void)0;
744       // [[p4]]
745     }
746   )";
747   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
748                            &Results,
749                        ASTContext &ASTCtx) {
750     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3", "p4"));
751 
752     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
753     ASSERT_THAT(FooDecl, NotNull());
754 
755     const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
756     ASSERT_THAT(BarDecl, NotNull());
757 
758     const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
759     ASSERT_THAT(BazDecl, NotNull());
760 
761     const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
762 
763     const StorageLocation *FooLoc = Env1.getStorageLocation(*FooDecl);
764     EXPECT_THAT(FooLoc, NotNull());
765     EXPECT_THAT(Env1.getStorageLocation(*BarDecl), IsNull());
766     EXPECT_THAT(Env1.getStorageLocation(*BazDecl), IsNull());
767 
768     const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
769     EXPECT_EQ(Env2.getStorageLocation(*FooDecl), FooLoc);
770     EXPECT_THAT(Env2.getStorageLocation(*BarDecl), NotNull());
771     EXPECT_THAT(Env2.getStorageLocation(*BazDecl), IsNull());
772 
773     const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
774     EXPECT_EQ(Env3.getStorageLocation(*FooDecl), FooLoc);
775     EXPECT_THAT(Env3.getStorageLocation(*BarDecl), IsNull());
776     EXPECT_THAT(Env3.getStorageLocation(*BazDecl), NotNull());
777 
778     const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4");
779     EXPECT_EQ(Env4.getStorageLocation(*FooDecl), FooLoc);
780     EXPECT_THAT(Env4.getStorageLocation(*BarDecl), IsNull());
781     EXPECT_THAT(Env4.getStorageLocation(*BazDecl), IsNull());
782   });
783 }
784 
785 TEST(TransferTest, BinaryOperatorAssign) {
786   std::string Code = R"(
787     void target() {
788       int Foo;
789       int Bar;
790       (Bar) = (Foo);
791       // [[p]]
792     }
793   )";
794   runDataflow(
795       Code,
796       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
797          ASTContext &ASTCtx) {
798         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
799         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
800 
801         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
802         ASSERT_THAT(FooDecl, NotNull());
803 
804         const Value *FooVal = Env.getValue(*FooDecl);
805         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
806 
807         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
808         ASSERT_THAT(BarDecl, NotNull());
809 
810         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
811       });
812 }
813 
814 TEST(TransferTest, BinaryOperatorAssignIntegerLiteral) {
815   std::string Code = R"(
816     void target() {
817       int Foo = 1;
818       // [[before]]
819       Foo = 2;
820       // [[after]]
821     }
822   )";
823   runDataflow(
824       Code,
825       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
826          ASTContext &ASTCtx) {
827         const Environment &Before =
828             getEnvironmentAtAnnotation(Results, "before");
829         const Environment &After = getEnvironmentAtAnnotation(Results, "after");
830 
831         const auto &ValBefore =
832             getValueForDecl<IntegerValue>(ASTCtx, Before, "Foo");
833         const auto &ValAfter =
834             getValueForDecl<IntegerValue>(ASTCtx, After, "Foo");
835         EXPECT_NE(&ValBefore, &ValAfter);
836       });
837 }
838 
839 TEST(TransferTest, VarDeclInitAssign) {
840   std::string Code = R"(
841     void target() {
842       int Foo;
843       int Bar = Foo;
844       // [[p]]
845     }
846   )";
847   runDataflow(
848       Code,
849       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
850          ASTContext &ASTCtx) {
851         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
852         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
853 
854         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
855         ASSERT_THAT(FooDecl, NotNull());
856 
857         const Value *FooVal = Env.getValue(*FooDecl);
858         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
859 
860         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
861         ASSERT_THAT(BarDecl, NotNull());
862 
863         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
864       });
865 }
866 
867 TEST(TransferTest, VarDeclInitAssignChained) {
868   std::string Code = R"(
869     void target() {
870       int Foo;
871       int Bar;
872       int Baz = (Bar = Foo);
873       // [[p]]
874     }
875   )";
876   runDataflow(
877       Code,
878       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
879          ASTContext &ASTCtx) {
880         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
881         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
882 
883         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
884         ASSERT_THAT(FooDecl, NotNull());
885 
886         const Value *FooVal = Env.getValue(*FooDecl);
887         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
888 
889         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
890         ASSERT_THAT(BarDecl, NotNull());
891 
892         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
893         ASSERT_THAT(BazDecl, NotNull());
894 
895         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
896         EXPECT_EQ(Env.getValue(*BazDecl), FooVal);
897       });
898 }
899 
900 TEST(TransferTest, VarDeclInitAssignPtrDeref) {
901   std::string Code = R"(
902     void target() {
903       int Foo;
904       int *Bar;
905       *(Bar) = Foo;
906       int Baz = *(Bar);
907       // [[p]]
908     }
909   )";
910   runDataflow(
911       Code,
912       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
913          ASTContext &ASTCtx) {
914         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
915         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
916 
917         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
918         ASSERT_THAT(FooDecl, NotNull());
919 
920         const Value *FooVal = Env.getValue(*FooDecl);
921         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
922 
923         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
924         ASSERT_THAT(BarDecl, NotNull());
925 
926         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
927         EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal);
928 
929         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
930         ASSERT_THAT(BazDecl, NotNull());
931 
932         EXPECT_EQ(Env.getValue(*BazDecl), FooVal);
933       });
934 }
935 
936 TEST(TransferTest, AssignToAndFromReference) {
937   std::string Code = R"(
938     void target() {
939       int Foo;
940       int Bar;
941       int &Baz = Foo;
942       // [[p1]]
943       Baz = Bar;
944       int Qux = Baz;
945       int &Quux = Baz;
946       // [[p2]]
947     }
948   )";
949   runDataflow(
950       Code,
951       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
952          ASTContext &ASTCtx) {
953         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
954         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
955         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
956 
957         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
958         ASSERT_THAT(FooDecl, NotNull());
959 
960         const Value *FooVal = Env1.getValue(*FooDecl);
961         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
962 
963         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
964         ASSERT_THAT(BarDecl, NotNull());
965 
966         const Value *BarVal = Env1.getValue(*BarDecl);
967         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
968 
969         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
970         ASSERT_THAT(BazDecl, NotNull());
971 
972         EXPECT_EQ(Env1.getValue(*BazDecl), FooVal);
973 
974         EXPECT_EQ(Env2.getValue(*BazDecl), BarVal);
975         EXPECT_EQ(Env2.getValue(*FooDecl), BarVal);
976 
977         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
978         ASSERT_THAT(QuxDecl, NotNull());
979         EXPECT_EQ(Env2.getValue(*QuxDecl), BarVal);
980 
981         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
982         ASSERT_THAT(QuuxDecl, NotNull());
983         EXPECT_EQ(Env2.getValue(*QuuxDecl), BarVal);
984       });
985 }
986 
987 TEST(TransferTest, MultipleParamDecls) {
988   std::string Code = R"(
989     void target(int Foo, int Bar) {
990       (void)0;
991       // [[p]]
992     }
993   )";
994   runDataflow(
995       Code,
996       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
997          ASTContext &ASTCtx) {
998         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
999         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1000 
1001         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1002         ASSERT_THAT(FooDecl, NotNull());
1003 
1004         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1005         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1006 
1007         const Value *FooVal = Env.getValue(*FooLoc);
1008         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1009 
1010         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1011         ASSERT_THAT(BarDecl, NotNull());
1012 
1013         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
1014         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1015 
1016         const Value *BarVal = Env.getValue(*BarLoc);
1017         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1018       });
1019 }
1020 
1021 TEST(TransferTest, StructParamDecl) {
1022   std::string Code = R"(
1023     struct A {
1024       int Bar;
1025     };
1026 
1027     void target(A Foo) {
1028       (void)Foo.Bar;
1029       // [[p]]
1030     }
1031   )";
1032   runDataflow(
1033       Code,
1034       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1035          ASTContext &ASTCtx) {
1036         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1037         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1038 
1039         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1040         ASSERT_THAT(FooDecl, NotNull());
1041 
1042         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1043         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1044 
1045         FieldDecl *BarDecl = nullptr;
1046         for (FieldDecl *Field : FooFields) {
1047           if (Field->getNameAsString() == "Bar") {
1048             BarDecl = Field;
1049           } else {
1050             FAIL() << "Unexpected field: " << Field->getNameAsString();
1051           }
1052         }
1053         ASSERT_THAT(BarDecl, NotNull());
1054 
1055         const auto *FooLoc =
1056             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
1057         const auto *BarLoc =
1058             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1059 
1060         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1061         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1062         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1063       });
1064 }
1065 
1066 TEST(TransferTest, ReferenceParamDecl) {
1067   std::string Code = R"(
1068     struct A {};
1069 
1070     void target(A &Foo) {
1071       (void)0;
1072       // [[p]]
1073     }
1074   )";
1075   runDataflow(
1076       Code,
1077       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1078          ASTContext &ASTCtx) {
1079         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1080         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1081 
1082         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1083         ASSERT_THAT(FooDecl, NotNull());
1084 
1085         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1086         ASSERT_TRUE(isa_and_nonnull<AggregateStorageLocation>(FooLoc));
1087 
1088         const Value *FooReferentVal = Env.getValue(*FooLoc);
1089         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal));
1090       });
1091 }
1092 
1093 TEST(TransferTest, PointerParamDecl) {
1094   std::string Code = R"(
1095     struct A {};
1096 
1097     void target(A *Foo) {
1098       (void)0;
1099       // [[p]]
1100     }
1101   )";
1102   runDataflow(
1103       Code,
1104       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1105          ASTContext &ASTCtx) {
1106         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1107         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1108 
1109         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1110         ASSERT_THAT(FooDecl, NotNull());
1111 
1112         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1113         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1114 
1115         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
1116         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
1117         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
1118 
1119         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
1120         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
1121       });
1122 }
1123 
1124 TEST(TransferTest, StructMember) {
1125   std::string Code = R"(
1126     struct A {
1127       int Bar;
1128     };
1129 
1130     void target(A Foo) {
1131       int Baz = Foo.Bar;
1132       // [[p]]
1133     }
1134   )";
1135   runDataflow(
1136       Code,
1137       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1138          ASTContext &ASTCtx) {
1139         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1140         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1141 
1142         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1143         ASSERT_THAT(FooDecl, NotNull());
1144 
1145         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1146         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1147 
1148         FieldDecl *BarDecl = nullptr;
1149         for (FieldDecl *Field : FooFields) {
1150           if (Field->getNameAsString() == "Bar") {
1151             BarDecl = Field;
1152           } else {
1153             FAIL() << "Unexpected field: " << Field->getNameAsString();
1154           }
1155         }
1156         ASSERT_THAT(BarDecl, NotNull());
1157 
1158         const auto *FooLoc =
1159             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
1160         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1161         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1162 
1163         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1164         ASSERT_THAT(BazDecl, NotNull());
1165 
1166         EXPECT_EQ(Env.getValue(*BazDecl), BarVal);
1167       });
1168 }
1169 
1170 TEST(TransferTest, StructMemberEnum) {
1171   std::string Code = R"(
1172     struct A {
1173       int Bar;
1174       enum E { ONE, TWO };
1175     };
1176 
1177     void target(A Foo) {
1178       A::E Baz = Foo.ONE;
1179       // [[p]]
1180     }
1181   )";
1182   // Minimal expectations -- we're just testing that it doesn't crash, since
1183   // enums aren't interpreted.
1184   runDataflow(
1185       Code,
1186       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1187          ASTContext &ASTCtx) {
1188         EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1189       });
1190 }
1191 
1192 TEST(TransferTest, DerivedBaseMemberClass) {
1193   std::string Code = R"(
1194     class A {
1195       int ADefault;
1196     protected:
1197       int AProtected;
1198     private:
1199       int APrivate;
1200     public:
1201       int APublic;
1202 
1203     private:
1204       friend void target();
1205     };
1206 
1207     class B : public A {
1208       int BDefault;
1209     protected:
1210       int BProtected;
1211     private:
1212       int BPrivate;
1213 
1214     private:
1215       friend void target();
1216     };
1217 
1218     void target() {
1219       B Foo;
1220       (void)Foo.ADefault;
1221       (void)Foo.AProtected;
1222       (void)Foo.APrivate;
1223       (void)Foo.APublic;
1224       (void)Foo.BDefault;
1225       (void)Foo.BProtected;
1226       (void)Foo.BPrivate;
1227       // [[p]]
1228     }
1229   )";
1230   runDataflow(
1231       Code,
1232       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1233          ASTContext &ASTCtx) {
1234         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1235         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1236 
1237         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1238         ASSERT_THAT(FooDecl, NotNull());
1239         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1240 
1241         // Derived-class fields.
1242         const FieldDecl *BDefaultDecl = nullptr;
1243         const FieldDecl *BProtectedDecl = nullptr;
1244         const FieldDecl *BPrivateDecl = nullptr;
1245         for (const FieldDecl *Field :
1246              FooDecl->getType()->getAsRecordDecl()->fields()) {
1247           if (Field->getNameAsString() == "BDefault") {
1248             BDefaultDecl = Field;
1249           } else if (Field->getNameAsString() == "BProtected") {
1250             BProtectedDecl = Field;
1251           } else if (Field->getNameAsString() == "BPrivate") {
1252             BPrivateDecl = Field;
1253           } else {
1254             FAIL() << "Unexpected field: " << Field->getNameAsString();
1255           }
1256         }
1257         ASSERT_THAT(BDefaultDecl, NotNull());
1258         ASSERT_THAT(BProtectedDecl, NotNull());
1259         ASSERT_THAT(BPrivateDecl, NotNull());
1260 
1261         // Base-class fields.
1262         const FieldDecl *ADefaultDecl = nullptr;
1263         const FieldDecl *APrivateDecl = nullptr;
1264         const FieldDecl *AProtectedDecl = nullptr;
1265         const FieldDecl *APublicDecl = nullptr;
1266         for (const clang::CXXBaseSpecifier &Base :
1267              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1268           QualType BaseType = Base.getType();
1269           ASSERT_TRUE(BaseType->isRecordType());
1270           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1271             if (Field->getNameAsString() == "ADefault") {
1272               ADefaultDecl = Field;
1273             } else if (Field->getNameAsString() == "AProtected") {
1274               AProtectedDecl = Field;
1275             } else if (Field->getNameAsString() == "APrivate") {
1276               APrivateDecl = Field;
1277             } else if (Field->getNameAsString() == "APublic") {
1278               APublicDecl = Field;
1279             } else {
1280               FAIL() << "Unexpected field: " << Field->getNameAsString();
1281             }
1282           }
1283         }
1284         ASSERT_THAT(ADefaultDecl, NotNull());
1285         ASSERT_THAT(AProtectedDecl, NotNull());
1286         ASSERT_THAT(APrivateDecl, NotNull());
1287         ASSERT_THAT(APublicDecl, NotNull());
1288 
1289         const auto &FooLoc =
1290             *cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
1291         const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1292 
1293         // Note: we can't test presence of children in `FooLoc`, because
1294         // `getChild` requires its argument be present (or fails an assert). So,
1295         // we limit to testing presence in `FooVal` and coherence between the
1296         // two.
1297 
1298         // Base-class fields.
1299         EXPECT_THAT(FooVal.getChild(*ADefaultDecl), NotNull());
1300         EXPECT_THAT(FooVal.getChild(*APrivateDecl), NotNull());
1301 
1302         EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull());
1303         EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)),
1304                   FooVal.getChild(*APublicDecl));
1305         EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull());
1306         EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)),
1307                   FooVal.getChild(*AProtectedDecl));
1308 
1309         // Derived-class fields.
1310         EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull());
1311         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)),
1312                   FooVal.getChild(*BDefaultDecl));
1313         EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull());
1314         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)),
1315                   FooVal.getChild(*BProtectedDecl));
1316         EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull());
1317         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)),
1318                   FooVal.getChild(*BPrivateDecl));
1319       });
1320 }
1321 
1322 static void derivedBaseMemberExpectations(
1323     const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1324     ASTContext &ASTCtx) {
1325   ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1326   const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1327 
1328   const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1329   ASSERT_THAT(FooDecl, NotNull());
1330 
1331   ASSERT_TRUE(FooDecl->getType()->isRecordType());
1332   const FieldDecl *BarDecl = nullptr;
1333   for (const clang::CXXBaseSpecifier &Base :
1334        FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1335     QualType BaseType = Base.getType();
1336     ASSERT_TRUE(BaseType->isStructureType());
1337 
1338     for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1339       if (Field->getNameAsString() == "Bar") {
1340         BarDecl = Field;
1341       } else {
1342         FAIL() << "Unexpected field: " << Field->getNameAsString();
1343       }
1344     }
1345   }
1346   ASSERT_THAT(BarDecl, NotNull());
1347 
1348   const auto &FooLoc =
1349       *cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
1350   const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1351   EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull());
1352   EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), FooVal.getChild(*BarDecl));
1353 }
1354 
1355 TEST(TransferTest, DerivedBaseMemberStructDefault) {
1356   std::string Code = R"(
1357     struct A {
1358       int Bar;
1359     };
1360     struct B : public A {
1361     };
1362 
1363     void target() {
1364       B Foo;
1365       (void)Foo.Bar;
1366       // [[p]]
1367     }
1368   )";
1369   runDataflow(Code, derivedBaseMemberExpectations);
1370 }
1371 
1372 TEST(TransferTest, DerivedBaseMemberPrivateFriend) {
1373   // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that
1374   // access.
1375   std::string Code = R"(
1376     struct A {
1377     private:
1378       friend void target();
1379       int Bar;
1380     };
1381     struct B : public A {
1382     };
1383 
1384     void target() {
1385       B Foo;
1386       (void)Foo.Bar;
1387       // [[p]]
1388     }
1389   )";
1390   runDataflow(Code, derivedBaseMemberExpectations);
1391 }
1392 
1393 TEST(TransferTest, ClassMember) {
1394   std::string Code = R"(
1395     class A {
1396     public:
1397       int Bar;
1398     };
1399 
1400     void target(A Foo) {
1401       int Baz = Foo.Bar;
1402       // [[p]]
1403     }
1404   )";
1405   runDataflow(
1406       Code,
1407       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1408          ASTContext &ASTCtx) {
1409         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1410         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1411 
1412         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1413         ASSERT_THAT(FooDecl, NotNull());
1414 
1415         ASSERT_TRUE(FooDecl->getType()->isClassType());
1416         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1417 
1418         FieldDecl *BarDecl = nullptr;
1419         for (FieldDecl *Field : FooFields) {
1420           if (Field->getNameAsString() == "Bar") {
1421             BarDecl = Field;
1422           } else {
1423             FAIL() << "Unexpected field: " << Field->getNameAsString();
1424           }
1425         }
1426         ASSERT_THAT(BarDecl, NotNull());
1427 
1428         const auto *FooLoc =
1429             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
1430         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1431         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1432 
1433         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1434         ASSERT_THAT(BazDecl, NotNull());
1435 
1436         EXPECT_EQ(Env.getValue(*BazDecl), BarVal);
1437       });
1438 }
1439 
1440 TEST(TransferTest, BaseClassInitializer) {
1441   using ast_matchers::cxxConstructorDecl;
1442   using ast_matchers::hasName;
1443   using ast_matchers::ofClass;
1444 
1445   std::string Code = R"(
1446     class A {
1447     public:
1448       A(int I) : Bar(I) {}
1449       int Bar;
1450     };
1451 
1452     class B : public A {
1453     public:
1454       B(int I) : A(I) {
1455         (void)0;
1456         // [[p]]
1457       }
1458     };
1459   )";
1460   ASSERT_THAT_ERROR(
1461       checkDataflow<NoopAnalysis>(
1462           AnalysisInputs<NoopAnalysis>(
1463               Code, cxxConstructorDecl(ofClass(hasName("B"))),
1464               [](ASTContext &C, Environment &) {
1465                 return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true);
1466               })
1467               .withASTBuildArgs(
1468                   {"-fsyntax-only", "-fno-delayed-template-parsing",
1469                    "-std=" + std::string(LangStandard::getLangStandardForKind(
1470                                              LangStandard::lang_cxx17)
1471                                              .getName())}),
1472           /*VerifyResults=*/
1473           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1474              const AnalysisOutputs &) {
1475             // Regression test to verify that base-class initializers do not
1476             // trigger an assertion. If we add support for such initializers in
1477             // the future, we can expand this test to check more specific
1478             // properties.
1479             EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1480           }),
1481       llvm::Succeeded());
1482 }
1483 
1484 TEST(TransferTest, ReferenceMember) {
1485   std::string Code = R"(
1486     struct A {
1487       int &Bar;
1488     };
1489 
1490     void target(A Foo) {
1491       int Baz = Foo.Bar;
1492       // [[p]]
1493     }
1494   )";
1495   runDataflow(
1496       Code,
1497       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1498          ASTContext &ASTCtx) {
1499         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1500         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1501 
1502         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1503         ASSERT_THAT(FooDecl, NotNull());
1504 
1505         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1506         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1507 
1508         FieldDecl *BarDecl = nullptr;
1509         for (FieldDecl *Field : FooFields) {
1510           if (Field->getNameAsString() == "Bar") {
1511             BarDecl = Field;
1512           } else {
1513             FAIL() << "Unexpected field: " << Field->getNameAsString();
1514           }
1515         }
1516         ASSERT_THAT(BarDecl, NotNull());
1517 
1518         const auto *FooLoc =
1519             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
1520         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1521         const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl));
1522         const auto *BarReferentVal =
1523             cast<IntegerValue>(Env.getValue(BarVal->getReferentLoc()));
1524 
1525         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1526         ASSERT_THAT(BazDecl, NotNull());
1527 
1528         EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal);
1529       });
1530 }
1531 
1532 TEST(TransferTest, StructThisMember) {
1533   std::string Code = R"(
1534     struct A {
1535       int Bar;
1536 
1537       struct B {
1538         int Baz;
1539       };
1540 
1541       B Qux;
1542 
1543       void target() {
1544         int Foo = Bar;
1545         int Quux = Qux.Baz;
1546         // [[p]]
1547       }
1548     };
1549   )";
1550   runDataflow(
1551       Code,
1552       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1553          ASTContext &ASTCtx) {
1554         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1555         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1556 
1557         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1558             Env.getThisPointeeStorageLocation());
1559         ASSERT_THAT(ThisLoc, NotNull());
1560 
1561         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1562         ASSERT_THAT(BarDecl, NotNull());
1563 
1564         const auto *BarLoc =
1565             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1566         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1567 
1568         const Value *BarVal = Env.getValue(*BarLoc);
1569         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1570 
1571         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1572         ASSERT_THAT(FooDecl, NotNull());
1573         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1574 
1575         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1576         ASSERT_THAT(QuxDecl, NotNull());
1577 
1578         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1579         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1580 
1581         FieldDecl *BazDecl = nullptr;
1582         for (FieldDecl *Field : QuxFields) {
1583           if (Field->getNameAsString() == "Baz") {
1584             BazDecl = Field;
1585           } else {
1586             FAIL() << "Unexpected field: " << Field->getNameAsString();
1587           }
1588         }
1589         ASSERT_THAT(BazDecl, NotNull());
1590 
1591         const auto *QuxLoc =
1592             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1593         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1594         ASSERT_THAT(QuxVal, NotNull());
1595 
1596         const auto *BazLoc =
1597             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1598         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1599         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1600 
1601         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1602         ASSERT_THAT(QuuxDecl, NotNull());
1603         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1604       });
1605 }
1606 
1607 TEST(TransferTest, ClassThisMember) {
1608   std::string Code = R"(
1609     class A {
1610       int Bar;
1611 
1612       class B {
1613       public:
1614         int Baz;
1615       };
1616 
1617       B Qux;
1618 
1619       void target() {
1620         int Foo = Bar;
1621         int Quux = Qux.Baz;
1622         // [[p]]
1623       }
1624     };
1625   )";
1626   runDataflow(
1627       Code,
1628       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1629          ASTContext &ASTCtx) {
1630         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1631         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1632 
1633         const auto *ThisLoc =
1634             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
1635 
1636         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1637         ASSERT_THAT(BarDecl, NotNull());
1638 
1639         const auto *BarLoc =
1640             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1641         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1642 
1643         const Value *BarVal = Env.getValue(*BarLoc);
1644         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1645 
1646         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1647         ASSERT_THAT(FooDecl, NotNull());
1648         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1649 
1650         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1651         ASSERT_THAT(QuxDecl, NotNull());
1652 
1653         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1654         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1655 
1656         FieldDecl *BazDecl = nullptr;
1657         for (FieldDecl *Field : QuxFields) {
1658           if (Field->getNameAsString() == "Baz") {
1659             BazDecl = Field;
1660           } else {
1661             FAIL() << "Unexpected field: " << Field->getNameAsString();
1662           }
1663         }
1664         ASSERT_THAT(BazDecl, NotNull());
1665 
1666         const auto *QuxLoc =
1667             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1668         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1669         ASSERT_THAT(QuxVal, NotNull());
1670 
1671         const auto *BazLoc =
1672             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1673         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1674         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1675 
1676         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1677         ASSERT_THAT(QuuxDecl, NotNull());
1678         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1679       });
1680 }
1681 
1682 TEST(TransferTest, UnionThisMember) {
1683   std::string Code = R"(
1684     union A {
1685       int Foo;
1686       int Bar;
1687 
1688       void target() {
1689         A a;
1690         // Mention the fields to ensure they're included in the analysis.
1691         (void)a.Foo;
1692         (void)a.Bar;
1693         // [[p]]
1694       }
1695     };
1696   )";
1697   runDataflow(
1698       Code,
1699       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1700          ASTContext &ASTCtx) {
1701         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1702         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1703 
1704         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1705             Env.getThisPointeeStorageLocation());
1706         ASSERT_THAT(ThisLoc, NotNull());
1707 
1708         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1709         ASSERT_THAT(FooDecl, NotNull());
1710 
1711         const auto *FooLoc =
1712             cast<ScalarStorageLocation>(&ThisLoc->getChild(*FooDecl));
1713         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1714 
1715         const Value *FooVal = Env.getValue(*FooLoc);
1716         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1717 
1718         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1719         ASSERT_THAT(BarDecl, NotNull());
1720 
1721         const auto *BarLoc =
1722             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1723         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1724 
1725         const Value *BarVal = Env.getValue(*BarLoc);
1726         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1727       });
1728 }
1729 
1730 TEST(TransferTest, StructThisInLambda) {
1731   std::string ThisCaptureCode = R"(
1732     struct A {
1733       void frob() {
1734         [this]() {
1735           int Foo = Bar;
1736           // [[p1]]
1737         }();
1738       }
1739 
1740       int Bar;
1741     };
1742   )";
1743   runDataflow(
1744       ThisCaptureCode,
1745       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1746          ASTContext &ASTCtx) {
1747         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
1748         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
1749 
1750         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1751             Env.getThisPointeeStorageLocation());
1752         ASSERT_THAT(ThisLoc, NotNull());
1753 
1754         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1755         ASSERT_THAT(BarDecl, NotNull());
1756 
1757         const auto *BarLoc =
1758             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1759         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1760 
1761         const Value *BarVal = Env.getValue(*BarLoc);
1762         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1763 
1764         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1765         ASSERT_THAT(FooDecl, NotNull());
1766         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1767       },
1768       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1769 
1770   std::string RefCaptureDefaultCode = R"(
1771     struct A {
1772       void frob() {
1773         [&]() {
1774           int Foo = Bar;
1775           // [[p2]]
1776         }();
1777       }
1778 
1779       int Bar;
1780     };
1781   )";
1782   runDataflow(
1783       RefCaptureDefaultCode,
1784       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1785          ASTContext &ASTCtx) {
1786         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
1787         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
1788 
1789         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1790             Env.getThisPointeeStorageLocation());
1791         ASSERT_THAT(ThisLoc, NotNull());
1792 
1793         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1794         ASSERT_THAT(BarDecl, NotNull());
1795 
1796         const auto *BarLoc =
1797             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1798         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1799 
1800         const Value *BarVal = Env.getValue(*BarLoc);
1801         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1802 
1803         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1804         ASSERT_THAT(FooDecl, NotNull());
1805         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1806       },
1807       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1808 
1809   std::string FreeFunctionLambdaCode = R"(
1810     void foo() {
1811       int Bar;
1812       [&]() {
1813         int Foo = Bar;
1814         // [[p3]]
1815       }();
1816     }
1817   )";
1818   runDataflow(
1819       FreeFunctionLambdaCode,
1820       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1821          ASTContext &ASTCtx) {
1822         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
1823         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
1824 
1825         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
1826       },
1827       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1828 }
1829 
1830 TEST(TransferTest, ConstructorInitializer) {
1831   std::string Code = R"(
1832     struct target {
1833       int Bar;
1834 
1835       target(int Foo) : Bar(Foo) {
1836         int Qux = Bar;
1837         // [[p]]
1838       }
1839     };
1840   )";
1841   runDataflow(
1842       Code,
1843       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1844          ASTContext &ASTCtx) {
1845         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1846         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1847 
1848         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1849             Env.getThisPointeeStorageLocation());
1850         ASSERT_THAT(ThisLoc, NotNull());
1851 
1852         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1853         ASSERT_THAT(FooDecl, NotNull());
1854 
1855         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
1856 
1857         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1858         ASSERT_THAT(QuxDecl, NotNull());
1859         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
1860       });
1861 }
1862 
1863 TEST(TransferTest, DefaultInitializer) {
1864   std::string Code = R"(
1865     struct target {
1866       int Bar;
1867       int Baz = Bar;
1868 
1869       target(int Foo) : Bar(Foo) {
1870         int Qux = Baz;
1871         // [[p]]
1872       }
1873     };
1874   )";
1875   runDataflow(
1876       Code,
1877       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1878          ASTContext &ASTCtx) {
1879         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1880         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1881 
1882         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1883             Env.getThisPointeeStorageLocation());
1884         ASSERT_THAT(ThisLoc, NotNull());
1885 
1886         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1887         ASSERT_THAT(FooDecl, NotNull());
1888 
1889         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
1890 
1891         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1892         ASSERT_THAT(QuxDecl, NotNull());
1893         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
1894       });
1895 }
1896 
1897 TEST(TransferTest, DefaultInitializerReference) {
1898   std::string Code = R"(
1899     struct target {
1900       int &Bar;
1901       int &Baz = Bar;
1902 
1903       target(int &Foo) : Bar(Foo) {
1904         int &Qux = Baz;
1905         // [[p]]
1906       }
1907     };
1908   )";
1909   runDataflow(
1910       Code,
1911       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1912          ASTContext &ASTCtx) {
1913         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1914         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1915 
1916         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1917             Env.getThisPointeeStorageLocation());
1918         ASSERT_THAT(ThisLoc, NotNull());
1919 
1920         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1921         ASSERT_THAT(FooDecl, NotNull());
1922 
1923         const auto *FooLoc = Env.getStorageLocation(*FooDecl);
1924 
1925         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1926         ASSERT_THAT(QuxDecl, NotNull());
1927 
1928         const auto *QuxLoc = Env.getStorageLocation(*QuxDecl);
1929         EXPECT_EQ(QuxLoc, FooLoc);
1930       });
1931 }
1932 
1933 TEST(TransferTest, TemporaryObject) {
1934   std::string Code = R"(
1935     struct A {
1936       int Bar;
1937     };
1938 
1939     void target() {
1940       A Foo = A();
1941       (void)Foo.Bar;
1942       // [[p]]
1943     }
1944   )";
1945   runDataflow(
1946       Code,
1947       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1948          ASTContext &ASTCtx) {
1949         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1950         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1951 
1952         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1953         ASSERT_THAT(FooDecl, NotNull());
1954 
1955         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1956         ASSERT_THAT(BarDecl, NotNull());
1957 
1958         const auto *FooLoc =
1959             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
1960         const auto *BarLoc =
1961             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1962 
1963         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1964         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1965         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1966       });
1967 }
1968 
1969 TEST(TransferTest, ElidableConstructor) {
1970   // This test is effectively the same as TransferTest.TemporaryObject, but
1971   // the code is compiled as C++ 14.
1972   std::string Code = R"(
1973     struct A {
1974       int Bar;
1975     };
1976 
1977     void target() {
1978       A Foo = A();
1979       (void)Foo.Bar;
1980       // [[p]]
1981     }
1982   )";
1983   runDataflow(
1984       Code,
1985       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1986          ASTContext &ASTCtx) {
1987         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1988         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1989 
1990         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1991         ASSERT_THAT(FooDecl, NotNull());
1992 
1993         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1994         ASSERT_THAT(BarDecl, NotNull());
1995 
1996         const auto *FooLoc =
1997             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
1998         const auto *BarLoc =
1999             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
2000 
2001         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
2002         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
2003         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
2004       },
2005       LangStandard::lang_cxx14);
2006 }
2007 
2008 TEST(TransferTest, AssignmentOperator) {
2009   std::string Code = R"(
2010     struct A {
2011       int Baz;
2012     };
2013 
2014     void target() {
2015       A Foo;
2016       A Bar;
2017       (void)Foo.Baz;
2018       // [[p1]]
2019       Foo = Bar;
2020       // [[p2]]
2021     }
2022   )";
2023   runDataflow(
2024       Code,
2025       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2026          ASTContext &ASTCtx) {
2027         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2028         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2029         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2030 
2031         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2032         ASSERT_THAT(FooDecl, NotNull());
2033 
2034         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2035         ASSERT_THAT(BarDecl, NotNull());
2036 
2037         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2038         ASSERT_THAT(BazDecl, NotNull());
2039 
2040         const auto *FooLoc1 =
2041             cast<AggregateStorageLocation>(Env1.getStorageLocation(*FooDecl));
2042         const auto *BarLoc1 =
2043             cast<AggregateStorageLocation>(Env1.getStorageLocation(*BarDecl));
2044 
2045         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
2046         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
2047         EXPECT_NE(FooVal1, BarVal1);
2048 
2049         const auto *FooBazVal1 =
2050             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
2051         const auto *BarBazVal1 =
2052             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
2053         EXPECT_NE(FooBazVal1, BarBazVal1);
2054 
2055         const auto *FooLoc2 =
2056             cast<AggregateStorageLocation>(Env2.getStorageLocation(*FooDecl));
2057         const auto *BarLoc2 =
2058             cast<AggregateStorageLocation>(Env2.getStorageLocation(*BarDecl));
2059 
2060         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
2061         const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2));
2062         EXPECT_EQ(FooVal2, BarVal2);
2063 
2064         const auto *FooBazVal2 =
2065             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
2066         const auto *BarBazVal2 =
2067             cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl)));
2068         EXPECT_EQ(FooBazVal2, BarBazVal2);
2069       });
2070 }
2071 
2072 TEST(TransferTest, CopyConstructor) {
2073   std::string Code = R"(
2074     struct A {
2075       int Baz;
2076     };
2077 
2078     void target() {
2079       A Foo;
2080       (void)Foo.Baz;
2081       A Bar = Foo;
2082       // [[p]]
2083     }
2084   )";
2085   runDataflow(
2086       Code,
2087       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2088          ASTContext &ASTCtx) {
2089         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2090         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2091 
2092         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2093         ASSERT_THAT(FooDecl, NotNull());
2094 
2095         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2096         ASSERT_THAT(BarDecl, NotNull());
2097 
2098         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2099         ASSERT_THAT(BazDecl, NotNull());
2100 
2101         const auto *FooLoc =
2102             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
2103         const auto *BarLoc =
2104             cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl));
2105 
2106         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
2107         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
2108         EXPECT_EQ(FooVal, BarVal);
2109 
2110         const auto *FooBazVal =
2111             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
2112         const auto *BarBazVal =
2113             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
2114         EXPECT_EQ(FooBazVal, BarBazVal);
2115       });
2116 }
2117 
2118 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2119   std::string Code = R"(
2120     struct A {
2121       int Baz;
2122       A() = default;
2123       A(const A& a, bool def = true) { Baz = a.Baz; }
2124     };
2125 
2126     void target() {
2127       A Foo;
2128       (void)Foo.Baz;
2129       A Bar = Foo;
2130       // [[p]]
2131     }
2132   )";
2133   runDataflow(
2134       Code,
2135       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2136          ASTContext &ASTCtx) {
2137         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2138         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2139 
2140         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2141         ASSERT_THAT(FooDecl, NotNull());
2142 
2143         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2144         ASSERT_THAT(BarDecl, NotNull());
2145 
2146         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2147         ASSERT_THAT(BazDecl, NotNull());
2148 
2149         const auto *FooLoc =
2150             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
2151         const auto *BarLoc =
2152             cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl));
2153 
2154         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
2155         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
2156         EXPECT_EQ(FooVal, BarVal);
2157 
2158         const auto *FooBazVal =
2159             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
2160         const auto *BarBazVal =
2161             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
2162         EXPECT_EQ(FooBazVal, BarBazVal);
2163       });
2164 }
2165 
2166 TEST(TransferTest, CopyConstructorWithParens) {
2167   std::string Code = R"(
2168     struct A {
2169       int Baz;
2170     };
2171 
2172     void target() {
2173       A Foo;
2174       (void)Foo.Baz;
2175       A Bar((A(Foo)));
2176       // [[p]]
2177     }
2178   )";
2179   runDataflow(
2180       Code,
2181       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2182          ASTContext &ASTCtx) {
2183         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2184         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2185 
2186         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2187         ASSERT_THAT(FooDecl, NotNull());
2188 
2189         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2190         ASSERT_THAT(BarDecl, NotNull());
2191 
2192         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2193         ASSERT_THAT(BazDecl, NotNull());
2194 
2195         const auto *FooLoc =
2196             cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl));
2197         const auto *BarLoc =
2198             cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl));
2199 
2200         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
2201         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
2202         EXPECT_EQ(FooVal, BarVal);
2203 
2204         const auto *FooBazVal =
2205             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
2206         const auto *BarBazVal =
2207             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
2208         EXPECT_EQ(FooBazVal, BarBazVal);
2209       });
2210 }
2211 
2212 TEST(TransferTest, MoveConstructor) {
2213   std::string Code = R"(
2214     namespace std {
2215 
2216     template <typename T> struct remove_reference      { using type = T; };
2217     template <typename T> struct remove_reference<T&>  { using type = T; };
2218     template <typename T> struct remove_reference<T&&> { using type = T; };
2219 
2220     template <typename T>
2221     using remove_reference_t = typename remove_reference<T>::type;
2222 
2223     template <typename T>
2224     std::remove_reference_t<T>&& move(T&& x);
2225 
2226     } // namespace std
2227 
2228     struct A {
2229       int Baz;
2230     };
2231 
2232     void target() {
2233       A Foo;
2234       A Bar;
2235       (void)Foo.Baz;
2236       // [[p1]]
2237       Foo = std::move(Bar);
2238       // [[p2]]
2239     }
2240   )";
2241   runDataflow(
2242       Code,
2243       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2244          ASTContext &ASTCtx) {
2245         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2246         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2247         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2248 
2249         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2250         ASSERT_THAT(FooDecl, NotNull());
2251 
2252         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2253         ASSERT_THAT(BarDecl, NotNull());
2254 
2255         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2256         ASSERT_THAT(BazDecl, NotNull());
2257 
2258         const auto *FooLoc1 =
2259             cast<AggregateStorageLocation>(Env1.getStorageLocation(*FooDecl));
2260         const auto *BarLoc1 =
2261             cast<AggregateStorageLocation>(Env1.getStorageLocation(*BarDecl));
2262 
2263         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
2264         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
2265         EXPECT_NE(FooVal1, BarVal1);
2266 
2267         const auto *FooBazVal1 =
2268             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
2269         const auto *BarBazVal1 =
2270             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
2271         EXPECT_NE(FooBazVal1, BarBazVal1);
2272 
2273         const auto *FooLoc2 =
2274             cast<AggregateStorageLocation>(Env2.getStorageLocation(*FooDecl));
2275         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
2276         EXPECT_EQ(FooVal2, BarVal1);
2277 
2278         const auto *FooBazVal2 =
2279             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
2280         EXPECT_EQ(FooBazVal2, BarBazVal1);
2281       });
2282 }
2283 
2284 TEST(TransferTest, BindTemporary) {
2285   std::string Code = R"(
2286     struct A {
2287       virtual ~A() = default;
2288 
2289       int Baz;
2290     };
2291 
2292     void target(A Foo) {
2293       int Bar = A(Foo).Baz;
2294       // [[p]]
2295     }
2296   )";
2297   runDataflow(
2298       Code,
2299       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2300          ASTContext &ASTCtx) {
2301         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2302         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2303 
2304         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2305         ASSERT_THAT(FooDecl, NotNull());
2306 
2307         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2308         ASSERT_THAT(BarDecl, NotNull());
2309 
2310         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2311         ASSERT_THAT(BazDecl, NotNull());
2312 
2313         const auto &FooVal = *cast<StructValue>(Env.getValue(*FooDecl));
2314         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2315         EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl));
2316       });
2317 }
2318 
2319 TEST(TransferTest, StaticCast) {
2320   std::string Code = R"(
2321     void target(int Foo) {
2322       int Bar = static_cast<int>(Foo);
2323       // [[p]]
2324     }
2325   )";
2326   runDataflow(
2327       Code,
2328       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2329          ASTContext &ASTCtx) {
2330         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2331         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2332 
2333         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2334         ASSERT_THAT(FooDecl, NotNull());
2335 
2336         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2337         ASSERT_THAT(BarDecl, NotNull());
2338 
2339         const auto *FooVal = Env.getValue(*FooDecl);
2340         const auto *BarVal = Env.getValue(*BarDecl);
2341         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2342         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2343         EXPECT_EQ(FooVal, BarVal);
2344       });
2345 }
2346 
2347 TEST(TransferTest, IntegralCast) {
2348   std::string Code = R"(
2349     void target(int Foo) {
2350       long Bar = Foo;
2351       // [[p]]
2352     }
2353   )";
2354   runDataflow(
2355       Code,
2356       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2357          ASTContext &ASTCtx) {
2358         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2359         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2360 
2361         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2362         ASSERT_THAT(FooDecl, NotNull());
2363 
2364         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2365         ASSERT_THAT(BarDecl, NotNull());
2366 
2367         const auto *FooVal = Env.getValue(*FooDecl);
2368         const auto *BarVal = Env.getValue(*BarDecl);
2369         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2370         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2371         EXPECT_EQ(FooVal, BarVal);
2372       });
2373 }
2374 
2375 TEST(TransferTest, IntegraltoBooleanCast) {
2376   std::string Code = R"(
2377     void target(int Foo) {
2378       bool Bar = Foo;
2379       // [[p]]
2380     }
2381   )";
2382   runDataflow(
2383       Code,
2384       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2385          ASTContext &ASTCtx) {
2386         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2387         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2388 
2389         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2390         ASSERT_THAT(FooDecl, NotNull());
2391 
2392         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2393         ASSERT_THAT(BarDecl, NotNull());
2394 
2395         const auto *FooVal = Env.getValue(*FooDecl);
2396         const auto *BarVal = Env.getValue(*BarDecl);
2397         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2398         EXPECT_TRUE(isa<BoolValue>(BarVal));
2399       });
2400 }
2401 
2402 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2403   std::string Code = R"(
2404     void target(bool Foo) {
2405       int Zab = Foo;
2406       bool Bar = Zab;
2407       // [[p]]
2408     }
2409   )";
2410   runDataflow(
2411       Code,
2412       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2413          ASTContext &ASTCtx) {
2414         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2415         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2416 
2417         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2418         ASSERT_THAT(FooDecl, NotNull());
2419 
2420         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2421         ASSERT_THAT(BarDecl, NotNull());
2422 
2423         const auto *FooVal = Env.getValue(*FooDecl);
2424         const auto *BarVal = Env.getValue(*BarDecl);
2425         EXPECT_TRUE(isa<BoolValue>(FooVal));
2426         EXPECT_TRUE(isa<BoolValue>(BarVal));
2427         EXPECT_EQ(FooVal, BarVal);
2428       });
2429 }
2430 
2431 TEST(TransferTest, NullToPointerCast) {
2432   std::string Code = R"(
2433     using my_nullptr_t = decltype(nullptr);
2434     struct Baz {};
2435     void target() {
2436       int *FooX = nullptr;
2437       int *FooY = nullptr;
2438       bool **Bar = nullptr;
2439       Baz *Baz = nullptr;
2440       my_nullptr_t Null = 0;
2441       // [[p]]
2442     }
2443   )";
2444   runDataflow(
2445       Code,
2446       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2447          ASTContext &ASTCtx) {
2448         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2449         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2450 
2451         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2452         ASSERT_THAT(FooXDecl, NotNull());
2453 
2454         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2455         ASSERT_THAT(FooYDecl, NotNull());
2456 
2457         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2458         ASSERT_THAT(BarDecl, NotNull());
2459 
2460         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2461         ASSERT_THAT(BazDecl, NotNull());
2462 
2463         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2464         ASSERT_THAT(NullDecl, NotNull());
2465 
2466         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
2467         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
2468         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2469         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
2470         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
2471 
2472         EXPECT_EQ(FooXVal, FooYVal);
2473         EXPECT_NE(FooXVal, BarVal);
2474         EXPECT_NE(FooXVal, BazVal);
2475         EXPECT_NE(BarVal, BazVal);
2476 
2477         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2478         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2479         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2480 
2481         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2482         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2483         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2484 
2485         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2486         EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc));
2487         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2488 
2489         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
2490         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2491         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2492       });
2493 }
2494 
2495 TEST(TransferTest, NullToMemberPointerCast) {
2496   std::string Code = R"(
2497     struct Foo {};
2498     void target(Foo *Foo) {
2499       int Foo::*MemberPointer = nullptr;
2500       // [[p]]
2501     }
2502   )";
2503   runDataflow(
2504       Code,
2505       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2506          ASTContext &ASTCtx) {
2507         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2508         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2509 
2510         const ValueDecl *MemberPointerDecl =
2511             findValueDecl(ASTCtx, "MemberPointer");
2512         ASSERT_THAT(MemberPointerDecl, NotNull());
2513 
2514         const auto *MemberPointerVal =
2515             cast<PointerValue>(Env.getValue(*MemberPointerDecl));
2516 
2517         const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc();
2518         EXPECT_THAT(Env.getValue(MemberLoc), IsNull());
2519       });
2520 }
2521 
2522 TEST(TransferTest, AddrOfValue) {
2523   std::string Code = R"(
2524     void target() {
2525       int Foo;
2526       int *Bar = &Foo;
2527       // [[p]]
2528     }
2529   )";
2530   runDataflow(
2531       Code,
2532       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2533          ASTContext &ASTCtx) {
2534         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2535         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2536 
2537         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2538         ASSERT_THAT(FooDecl, NotNull());
2539 
2540         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2541         ASSERT_THAT(BarDecl, NotNull());
2542 
2543         const auto *FooLoc =
2544             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
2545         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2546         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2547       });
2548 }
2549 
2550 TEST(TransferTest, AddrOfReference) {
2551   std::string Code = R"(
2552     void target(int *Foo) {
2553       int *Bar = &(*Foo);
2554       // [[p]]
2555     }
2556   )";
2557   runDataflow(
2558       Code,
2559       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2560          ASTContext &ASTCtx) {
2561         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2562         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2563 
2564         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2565         ASSERT_THAT(FooDecl, NotNull());
2566 
2567         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2568         ASSERT_THAT(BarDecl, NotNull());
2569 
2570         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
2571         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2572         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2573       });
2574 }
2575 
2576 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
2577   std::string Code = R"(
2578     template <typename T>
2579     void target() {}
2580   )";
2581   ASSERT_THAT_ERROR(
2582       runDataflowReturnError(
2583           Code,
2584           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2585              ASTContext &ASTCtx) {},
2586           {BuiltinOptions()}),
2587       llvm::FailedWithMessage("Cannot analyze templated declarations"));
2588 }
2589 
2590 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
2591   std::string Code = R"(
2592     template <typename T>
2593     struct A {
2594       void target() {}
2595     };
2596   )";
2597   ASSERT_THAT_ERROR(
2598       runDataflowReturnError(
2599           Code,
2600           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2601              ASTContext &ASTCtx) {},
2602           {BuiltinOptions()}),
2603       llvm::FailedWithMessage("Cannot analyze templated declarations"));
2604 }
2605 
2606 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
2607   std::string Code = R"(
2608     struct A {};
2609 
2610     void target(A Foo, A Bar, bool Cond) {
2611       A Baz = Cond ?  Foo : Bar;
2612       /*[[p]]*/
2613     }
2614   )";
2615   runDataflow(
2616       Code,
2617       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2618          ASTContext &ASTCtx) {
2619         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2620         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2621 
2622         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2623         ASSERT_THAT(FooDecl, NotNull());
2624 
2625         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2626         ASSERT_THAT(BarDecl, NotNull());
2627 
2628         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2629         ASSERT_THAT(BazDecl, NotNull());
2630 
2631         const auto *FooVal = cast<StructValue>(Env.getValue(*FooDecl));
2632         const auto *BarVal = cast<StructValue>(Env.getValue(*BarDecl));
2633 
2634         const auto *BazVal = dyn_cast<StructValue>(Env.getValue(*BazDecl));
2635         ASSERT_THAT(BazVal, NotNull());
2636 
2637         EXPECT_NE(BazVal, FooVal);
2638         EXPECT_NE(BazVal, BarVal);
2639       });
2640 }
2641 
2642 TEST(TransferTest, VarDeclInDoWhile) {
2643   std::string Code = R"(
2644     void target(int *Foo) {
2645       do {
2646         int Bar = *Foo;
2647         // [[in_loop]]
2648       } while (false);
2649       (void)0;
2650       // [[after_loop]]
2651     }
2652   )";
2653   runDataflow(
2654       Code,
2655       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2656          ASTContext &ASTCtx) {
2657         const Environment &EnvInLoop =
2658             getEnvironmentAtAnnotation(Results, "in_loop");
2659         const Environment &EnvAfterLoop =
2660             getEnvironmentAtAnnotation(Results, "after_loop");
2661 
2662         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2663         ASSERT_THAT(FooDecl, NotNull());
2664 
2665         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2666         ASSERT_THAT(BarDecl, NotNull());
2667 
2668         const auto *FooVal =
2669             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
2670         const auto *FooPointeeVal =
2671             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
2672 
2673         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
2674         EXPECT_EQ(BarVal, FooPointeeVal);
2675 
2676         // FIXME: This assertion documents current behavior, but we would prefer
2677         // declarations to be removed from the environment when their lifetime
2678         // ends. Once this is the case, change this assertion accordingly.
2679         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), BarVal);
2680       });
2681 }
2682 
2683 TEST(TransferTest, UnreachableAfterWhileTrue) {
2684   std::string Code = R"(
2685     void target() {
2686       while (true) {}
2687       (void)0;
2688       /*[[p]]*/
2689     }
2690   )";
2691   runDataflow(
2692       Code,
2693       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2694          ASTContext &ASTCtx) {
2695         // The node after the while-true is pruned because it is trivially
2696         // known to be unreachable.
2697         ASSERT_TRUE(Results.empty());
2698       });
2699 }
2700 
2701 TEST(TransferTest, AggregateInitialization) {
2702   std::string BracesCode = R"(
2703     struct A {
2704       int Foo;
2705     };
2706 
2707     struct B {
2708       int Bar;
2709       A Baz;
2710       int Qux;
2711     };
2712 
2713     void target(int BarArg, int FooArg, int QuxArg) {
2714       B Quux{BarArg, {FooArg}, QuxArg};
2715       /*[[p]]*/
2716     }
2717   )";
2718   std::string BraceEllisionCode = R"(
2719     struct A {
2720       int Foo;
2721     };
2722 
2723     struct B {
2724       int Bar;
2725       A Baz;
2726       int Qux;
2727     };
2728 
2729     void target(int BarArg, int FooArg, int QuxArg) {
2730       B Quux = {BarArg, FooArg, QuxArg};
2731       /*[[p]]*/
2732     }
2733   )";
2734   for (const std::string &Code : {BracesCode, BraceEllisionCode}) {
2735     runDataflow(
2736         Code,
2737         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2738            ASTContext &ASTCtx) {
2739           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2740           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2741 
2742           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2743           ASSERT_THAT(FooDecl, NotNull());
2744 
2745           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2746           ASSERT_THAT(BarDecl, NotNull());
2747 
2748           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2749           ASSERT_THAT(BazDecl, NotNull());
2750 
2751           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2752           ASSERT_THAT(QuxDecl, NotNull());
2753 
2754           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2755           ASSERT_THAT(FooArgDecl, NotNull());
2756 
2757           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2758           ASSERT_THAT(BarArgDecl, NotNull());
2759 
2760           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2761           ASSERT_THAT(QuxArgDecl, NotNull());
2762 
2763           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2764           ASSERT_THAT(QuuxDecl, NotNull());
2765 
2766           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
2767           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
2768           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
2769 
2770           const auto *QuuxVal = cast<StructValue>(Env.getValue(*QuuxDecl));
2771           ASSERT_THAT(QuuxVal, NotNull());
2772 
2773           const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl));
2774           ASSERT_THAT(BazVal, NotNull());
2775 
2776           EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal);
2777           EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal);
2778           EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal);
2779         });
2780   }
2781 }
2782 
2783 TEST(TransferTest, AssignToUnionMember) {
2784   std::string Code = R"(
2785     union A {
2786       int Foo;
2787     };
2788 
2789     void target(int Bar) {
2790       A Baz;
2791       Baz.Foo = Bar;
2792       // [[p]]
2793     }
2794   )";
2795   runDataflow(
2796       Code,
2797       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2798          ASTContext &ASTCtx) {
2799         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2800         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2801 
2802         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2803         ASSERT_THAT(BazDecl, NotNull());
2804         ASSERT_TRUE(BazDecl->getType()->isUnionType());
2805 
2806         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
2807         FieldDecl *FooDecl = nullptr;
2808         for (FieldDecl *Field : BazFields) {
2809           if (Field->getNameAsString() == "Foo") {
2810             FooDecl = Field;
2811           } else {
2812             FAIL() << "Unexpected field: " << Field->getNameAsString();
2813           }
2814         }
2815         ASSERT_THAT(FooDecl, NotNull());
2816 
2817         const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2818             Env.getStorageLocation(*BazDecl));
2819         ASSERT_THAT(BazLoc, NotNull());
2820         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
2821 
2822         const auto *BazVal = cast<StructValue>(Env.getValue(*BazLoc));
2823         const auto *FooValFromBazVal = cast<IntegerValue>(BazVal->getChild(*FooDecl));
2824         const auto *FooValFromBazLoc = cast<IntegerValue>(Env.getValue(BazLoc->getChild(*FooDecl)));
2825         EXPECT_EQ(FooValFromBazLoc, FooValFromBazVal);
2826 
2827         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2828         ASSERT_THAT(BarDecl, NotNull());
2829         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
2830         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2831 
2832         EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazVal);
2833         EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazLoc);
2834       });
2835 }
2836 
2837 TEST(TransferTest, AssignFromBoolLiteral) {
2838   std::string Code = R"(
2839     void target() {
2840       bool Foo = true;
2841       bool Bar = false;
2842       // [[p]]
2843     }
2844   )";
2845   runDataflow(
2846       Code,
2847       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2848          ASTContext &ASTCtx) {
2849         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2850         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2851 
2852         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2853         ASSERT_THAT(FooDecl, NotNull());
2854 
2855         const auto *FooVal =
2856             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
2857         ASSERT_THAT(FooVal, NotNull());
2858 
2859         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2860         ASSERT_THAT(BarDecl, NotNull());
2861 
2862         const auto *BarVal =
2863             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl));
2864         ASSERT_THAT(BarVal, NotNull());
2865 
2866         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
2867         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
2868       });
2869 }
2870 
2871 TEST(TransferTest, AssignFromCompositeBoolExpression) {
2872   {
2873     std::string Code = R"(
2874     void target(bool Foo, bool Bar, bool Qux) {
2875       bool Baz = (Foo) && (Bar || Qux);
2876       // [[p]]
2877     }
2878   )";
2879     runDataflow(
2880         Code,
2881         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2882            ASTContext &ASTCtx) {
2883           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2884           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2885 
2886           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2887           ASSERT_THAT(FooDecl, NotNull());
2888 
2889           const auto *FooVal =
2890               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
2891           ASSERT_THAT(FooVal, NotNull());
2892 
2893           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2894           ASSERT_THAT(BarDecl, NotNull());
2895 
2896           const auto *BarVal =
2897               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
2898           ASSERT_THAT(BarVal, NotNull());
2899 
2900           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2901           ASSERT_THAT(QuxDecl, NotNull());
2902 
2903           const auto *QuxVal =
2904               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
2905           ASSERT_THAT(QuxVal, NotNull());
2906 
2907           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2908           ASSERT_THAT(BazDecl, NotNull());
2909 
2910           const auto *BazVal =
2911               dyn_cast_or_null<ConjunctionValue>(Env.getValue(*BazDecl));
2912           ASSERT_THAT(BazVal, NotNull());
2913           EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
2914 
2915           const auto *BazRightSubValVal =
2916               cast<DisjunctionValue>(&BazVal->getRightSubValue());
2917           EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
2918           EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
2919         });
2920   }
2921 
2922   {
2923     std::string Code = R"(
2924     void target(bool Foo, bool Bar, bool Qux) {
2925       bool Baz = (Foo && Qux) || (Bar);
2926       // [[p]]
2927     }
2928   )";
2929     runDataflow(
2930         Code,
2931         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2932            ASTContext &ASTCtx) {
2933           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2934           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2935 
2936           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2937           ASSERT_THAT(FooDecl, NotNull());
2938 
2939           const auto *FooVal =
2940               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
2941           ASSERT_THAT(FooVal, NotNull());
2942 
2943           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2944           ASSERT_THAT(BarDecl, NotNull());
2945 
2946           const auto *BarVal =
2947               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
2948           ASSERT_THAT(BarVal, NotNull());
2949 
2950           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2951           ASSERT_THAT(QuxDecl, NotNull());
2952 
2953           const auto *QuxVal =
2954               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
2955           ASSERT_THAT(QuxVal, NotNull());
2956 
2957           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2958           ASSERT_THAT(BazDecl, NotNull());
2959 
2960           const auto *BazVal =
2961               dyn_cast_or_null<DisjunctionValue>(Env.getValue(*BazDecl));
2962           ASSERT_THAT(BazVal, NotNull());
2963 
2964           const auto *BazLeftSubValVal =
2965               cast<ConjunctionValue>(&BazVal->getLeftSubValue());
2966           EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal);
2967           EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal);
2968 
2969           EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
2970         });
2971   }
2972 
2973   {
2974     std::string Code = R"(
2975       void target(bool A, bool B, bool C, bool D) {
2976         bool Foo = ((A && B) && C) && D;
2977         // [[p]]
2978       }
2979     )";
2980     runDataflow(
2981         Code,
2982         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2983            ASTContext &ASTCtx) {
2984           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2985           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2986 
2987           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
2988           ASSERT_THAT(ADecl, NotNull());
2989 
2990           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
2991           ASSERT_THAT(AVal, NotNull());
2992 
2993           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2994           ASSERT_THAT(BDecl, NotNull());
2995 
2996           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
2997           ASSERT_THAT(BVal, NotNull());
2998 
2999           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3000           ASSERT_THAT(CDecl, NotNull());
3001 
3002           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3003           ASSERT_THAT(CVal, NotNull());
3004 
3005           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3006           ASSERT_THAT(DDecl, NotNull());
3007 
3008           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3009           ASSERT_THAT(DVal, NotNull());
3010 
3011           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3012           ASSERT_THAT(FooDecl, NotNull());
3013 
3014           const auto *FooVal =
3015               dyn_cast_or_null<ConjunctionValue>(Env.getValue(*FooDecl));
3016           ASSERT_THAT(FooVal, NotNull());
3017 
3018           const auto &FooLeftSubVal =
3019               cast<ConjunctionValue>(FooVal->getLeftSubValue());
3020           const auto &FooLeftLeftSubVal =
3021               cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue());
3022           EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal);
3023           EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal);
3024           EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal);
3025           EXPECT_EQ(&FooVal->getRightSubValue(), DVal);
3026         });
3027   }
3028 }
3029 
3030 TEST(TransferTest, AssignFromBoolNegation) {
3031   std::string Code = R"(
3032     void target() {
3033       bool Foo = true;
3034       bool Bar = !(Foo);
3035       // [[p]]
3036     }
3037   )";
3038   runDataflow(
3039       Code,
3040       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3041          ASTContext &ASTCtx) {
3042         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3043         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3044 
3045         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3046         ASSERT_THAT(FooDecl, NotNull());
3047 
3048         const auto *FooVal =
3049             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3050         ASSERT_THAT(FooVal, NotNull());
3051 
3052         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3053         ASSERT_THAT(BarDecl, NotNull());
3054 
3055         const auto *BarVal =
3056             dyn_cast_or_null<NegationValue>(Env.getValue(*BarDecl));
3057         ASSERT_THAT(BarVal, NotNull());
3058 
3059         EXPECT_EQ(&BarVal->getSubVal(), FooVal);
3060       });
3061 }
3062 
3063 TEST(TransferTest, BuiltinExpect) {
3064   std::string Code = R"(
3065     void target(long Foo) {
3066       long Bar = __builtin_expect(Foo, true);
3067       /*[[p]]*/
3068     }
3069   )";
3070   runDataflow(
3071       Code,
3072       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3073          ASTContext &ASTCtx) {
3074         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3075         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3076 
3077         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3078         ASSERT_THAT(FooDecl, NotNull());
3079 
3080         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3081         ASSERT_THAT(BarDecl, NotNull());
3082 
3083         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3084       });
3085 }
3086 
3087 // `__builtin_expect` takes and returns a `long` argument, so other types
3088 // involve casts. This verifies that we identify the input and output in that
3089 // case.
3090 TEST(TransferTest, BuiltinExpectBoolArg) {
3091   std::string Code = R"(
3092     void target(bool Foo) {
3093       bool Bar = __builtin_expect(Foo, true);
3094       /*[[p]]*/
3095     }
3096   )";
3097   runDataflow(
3098       Code,
3099       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3100          ASTContext &ASTCtx) {
3101         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3102         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3103 
3104         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3105         ASSERT_THAT(FooDecl, NotNull());
3106 
3107         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3108         ASSERT_THAT(BarDecl, NotNull());
3109 
3110         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3111       });
3112 }
3113 
3114 TEST(TransferTest, BuiltinUnreachable) {
3115   std::string Code = R"(
3116     void target(bool Foo) {
3117       bool Bar = false;
3118       if (Foo)
3119         Bar = Foo;
3120       else
3121         __builtin_unreachable();
3122       (void)0;
3123       /*[[p]]*/
3124     }
3125   )";
3126   runDataflow(
3127       Code,
3128       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3129          ASTContext &ASTCtx) {
3130         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3131         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3132 
3133         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3134         ASSERT_THAT(FooDecl, NotNull());
3135 
3136         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3137         ASSERT_THAT(BarDecl, NotNull());
3138 
3139         // `__builtin_unreachable` promises that the code is
3140         // unreachable, so the compiler treats the "then" branch as the
3141         // only possible predecessor of this statement.
3142         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3143       });
3144 }
3145 
3146 TEST(TransferTest, BuiltinTrap) {
3147   std::string Code = R"(
3148     void target(bool Foo) {
3149       bool Bar = false;
3150       if (Foo)
3151         Bar = Foo;
3152       else
3153         __builtin_trap();
3154       (void)0;
3155       /*[[p]]*/
3156     }
3157   )";
3158   runDataflow(
3159       Code,
3160       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3161          ASTContext &ASTCtx) {
3162         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3163         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3164 
3165         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3166         ASSERT_THAT(FooDecl, NotNull());
3167 
3168         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3169         ASSERT_THAT(BarDecl, NotNull());
3170 
3171         // `__builtin_trap` ensures program termination, so only the
3172         // "then" branch is a predecessor of this statement.
3173         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3174       });
3175 }
3176 
3177 TEST(TransferTest, BuiltinDebugTrap) {
3178   std::string Code = R"(
3179     void target(bool Foo) {
3180       bool Bar = false;
3181       if (Foo)
3182         Bar = Foo;
3183       else
3184         __builtin_debugtrap();
3185       (void)0;
3186       /*[[p]]*/
3187     }
3188   )";
3189   runDataflow(
3190       Code,
3191       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3192          ASTContext &ASTCtx) {
3193         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3194         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3195 
3196         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3197         ASSERT_THAT(FooDecl, NotNull());
3198 
3199         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3200         ASSERT_THAT(BarDecl, NotNull());
3201 
3202         // `__builtin_debugtrap` doesn't ensure program termination.
3203         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3204       });
3205 }
3206 
3207 TEST(TransferTest, StaticIntSingleVarDecl) {
3208   std::string Code = R"(
3209     void target() {
3210       static int Foo;
3211       // [[p]]
3212     }
3213   )";
3214   runDataflow(
3215       Code,
3216       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3217          ASTContext &ASTCtx) {
3218         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3219         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3220 
3221         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3222         ASSERT_THAT(FooDecl, NotNull());
3223 
3224         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3225         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3226 
3227         const Value *FooVal = Env.getValue(*FooLoc);
3228         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3229       });
3230 }
3231 
3232 TEST(TransferTest, StaticIntGroupVarDecl) {
3233   std::string Code = R"(
3234     void target() {
3235       static int Foo, Bar;
3236       (void)0;
3237       // [[p]]
3238     }
3239   )";
3240   runDataflow(
3241       Code,
3242       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3243          ASTContext &ASTCtx) {
3244         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3245         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3246 
3247         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3248         ASSERT_THAT(FooDecl, NotNull());
3249 
3250         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3251         ASSERT_THAT(BarDecl, NotNull());
3252 
3253         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3254         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3255 
3256         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3257         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3258 
3259         const Value *FooVal = Env.getValue(*FooLoc);
3260         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3261 
3262         const Value *BarVal = Env.getValue(*BarLoc);
3263         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3264 
3265         EXPECT_NE(FooVal, BarVal);
3266       });
3267 }
3268 
3269 TEST(TransferTest, GlobalIntVarDecl) {
3270   std::string Code = R"(
3271     static int Foo;
3272 
3273     void target() {
3274       int Bar = Foo;
3275       int Baz = Foo;
3276       // [[p]]
3277     }
3278   )";
3279   runDataflow(
3280       Code,
3281       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3282          ASTContext &ASTCtx) {
3283         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3284         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3285 
3286         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3287         ASSERT_THAT(BarDecl, NotNull());
3288 
3289         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3290         ASSERT_THAT(BazDecl, NotNull());
3291 
3292         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3293         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3294         EXPECT_EQ(BarVal, BazVal);
3295       });
3296 }
3297 
3298 TEST(TransferTest, StaticMemberIntVarDecl) {
3299   std::string Code = R"(
3300     struct A {
3301       static int Foo;
3302     };
3303 
3304     void target(A a) {
3305       int Bar = a.Foo;
3306       int Baz = a.Foo;
3307       // [[p]]
3308     }
3309   )";
3310   runDataflow(
3311       Code,
3312       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3313          ASTContext &ASTCtx) {
3314         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3315         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3316 
3317         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3318         ASSERT_THAT(BarDecl, NotNull());
3319 
3320         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3321         ASSERT_THAT(BazDecl, NotNull());
3322 
3323         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3324         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3325         EXPECT_EQ(BarVal, BazVal);
3326       });
3327 }
3328 
3329 TEST(TransferTest, StaticMemberRefVarDecl) {
3330   std::string Code = R"(
3331     struct A {
3332       static int &Foo;
3333     };
3334 
3335     void target(A a) {
3336       int Bar = a.Foo;
3337       int Baz = a.Foo;
3338       // [[p]]
3339     }
3340   )";
3341   runDataflow(
3342       Code,
3343       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3344          ASTContext &ASTCtx) {
3345         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3346         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3347 
3348         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3349         ASSERT_THAT(BarDecl, NotNull());
3350 
3351         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3352         ASSERT_THAT(BazDecl, NotNull());
3353 
3354         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3355         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3356         EXPECT_EQ(BarVal, BazVal);
3357       });
3358 }
3359 
3360 TEST(TransferTest, AssignMemberBeforeCopy) {
3361   std::string Code = R"(
3362     struct A {
3363       int Foo;
3364     };
3365 
3366     void target() {
3367       A A1;
3368       A A2;
3369       int Bar;
3370       A1.Foo = Bar;
3371       A2 = A1;
3372       // [[p]]
3373     }
3374   )";
3375   runDataflow(
3376       Code,
3377       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3378          ASTContext &ASTCtx) {
3379         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3380         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3381 
3382         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3383         ASSERT_THAT(FooDecl, NotNull());
3384 
3385         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3386         ASSERT_THAT(BarDecl, NotNull());
3387 
3388         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3389         ASSERT_THAT(A1Decl, NotNull());
3390 
3391         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3392         ASSERT_THAT(A2Decl, NotNull());
3393 
3394         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3395 
3396         const auto *A2Val = cast<StructValue>(Env.getValue(*A2Decl));
3397         EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
3398       });
3399 }
3400 
3401 TEST(TransferTest, BooleanEquality) {
3402   std::string Code = R"(
3403     void target(bool Bar) {
3404       bool Foo = true;
3405       if (Bar == Foo) {
3406         (void)0;
3407         /*[[p-then]]*/
3408       } else {
3409         (void)0;
3410         /*[[p-else]]*/
3411       }
3412     }
3413   )";
3414   runDataflow(
3415       Code,
3416       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3417          ASTContext &ASTCtx) {
3418         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3419         const Environment &EnvThen =
3420             getEnvironmentAtAnnotation(Results, "p-then");
3421         const Environment &EnvElse =
3422             getEnvironmentAtAnnotation(Results, "p-else");
3423 
3424         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3425         ASSERT_THAT(BarDecl, NotNull());
3426 
3427         auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl));
3428         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3429 
3430         auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl));
3431         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
3432       });
3433 }
3434 
3435 TEST(TransferTest, BooleanInequality) {
3436   std::string Code = R"(
3437     void target(bool Bar) {
3438       bool Foo = true;
3439       if (Bar != Foo) {
3440         (void)0;
3441         /*[[p-then]]*/
3442       } else {
3443         (void)0;
3444         /*[[p-else]]*/
3445       }
3446     }
3447   )";
3448   runDataflow(
3449       Code,
3450       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3451          ASTContext &ASTCtx) {
3452         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3453         const Environment &EnvThen =
3454             getEnvironmentAtAnnotation(Results, "p-then");
3455         const Environment &EnvElse =
3456             getEnvironmentAtAnnotation(Results, "p-else");
3457 
3458         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3459         ASSERT_THAT(BarDecl, NotNull());
3460 
3461         auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl));
3462         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
3463 
3464         auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl));
3465         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3466       });
3467 }
3468 
3469 TEST(TransferTest, IntegerLiteralEquality) {
3470   std::string Code = R"(
3471     void target() {
3472       bool equal = (42 == 42);
3473       // [[p]]
3474     }
3475   )";
3476   runDataflow(
3477       Code,
3478       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3479          ASTContext &ASTCtx) {
3480         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3481 
3482         auto &Equal = getValueForDecl<BoolValue>(ASTCtx, Env, "equal");
3483         EXPECT_TRUE(Env.flowConditionImplies(Equal));
3484       });
3485 }
3486 
3487 TEST(TransferTest, CorrelatedBranches) {
3488   std::string Code = R"(
3489     void target(bool B, bool C) {
3490       if (B) {
3491         return;
3492       }
3493       (void)0;
3494       /*[[p0]]*/
3495       if (C) {
3496         B = true;
3497         /*[[p1]]*/
3498       }
3499       if (B) {
3500         (void)0;
3501         /*[[p2]]*/
3502       }
3503     }
3504   )";
3505   runDataflow(
3506       Code,
3507       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3508          ASTContext &ASTCtx) {
3509         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3510 
3511         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3512         ASSERT_THAT(CDecl, NotNull());
3513 
3514         {
3515           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3516           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3517           ASSERT_THAT(BDecl, NotNull());
3518           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl));
3519 
3520           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3521         }
3522 
3523         {
3524           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3525           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl));
3526           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3527         }
3528 
3529         {
3530           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3531           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl));
3532           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3533         }
3534       });
3535 }
3536 
3537 TEST(TransferTest, LoopWithAssignmentConverges) {
3538   std::string Code = R"(
3539     bool foo();
3540 
3541     void target() {
3542        do {
3543         bool Bar = foo();
3544         if (Bar) break;
3545         (void)Bar;
3546         /*[[p]]*/
3547       } while (true);
3548     }
3549   )";
3550   // The key property that we are verifying is implicit in `runDataflow` --
3551   // namely, that the analysis succeeds, rather than hitting the maximum number
3552   // of iterations.
3553   runDataflow(
3554       Code,
3555       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3556          ASTContext &ASTCtx) {
3557         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3558         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3559 
3560         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3561         ASSERT_THAT(BarDecl, NotNull());
3562 
3563         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
3564         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3565       });
3566 }
3567 
3568 TEST(TransferTest, LoopWithStagedAssignments) {
3569   std::string Code = R"(
3570     bool foo();
3571 
3572     void target() {
3573       bool Bar = false;
3574       bool Err = false;
3575       while (foo()) {
3576         if (Bar)
3577           Err = true;
3578         Bar = true;
3579         /*[[p]]*/
3580       }
3581     }
3582   )";
3583   runDataflow(
3584       Code,
3585       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3586          ASTContext &ASTCtx) {
3587         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3588         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3589 
3590         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3591         ASSERT_THAT(BarDecl, NotNull());
3592         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3593         ASSERT_THAT(ErrDecl, NotNull());
3594 
3595         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
3596         auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl));
3597         EXPECT_TRUE(Env.flowConditionImplies(BarVal));
3598         // An unsound analysis, for example only evaluating the loop once, can
3599         // conclude that `Err` is false. So, we test that this conclusion is not
3600         // reached.
3601         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal)));
3602       });
3603 }
3604 
3605 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3606   std::string Code = R"(
3607     bool &foo();
3608 
3609     void target() {
3610        do {
3611         bool& Bar = foo();
3612         if (Bar) break;
3613         (void)Bar;
3614         /*[[p]]*/
3615       } while (true);
3616     }
3617   )";
3618   // The key property that we are verifying is that the analysis succeeds,
3619   // rather than hitting the maximum number of iterations.
3620   runDataflow(
3621       Code,
3622       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3623          ASTContext &ASTCtx) {
3624         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3625         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3626 
3627         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3628         ASSERT_THAT(BarDecl, NotNull());
3629 
3630         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
3631         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3632       });
3633 }
3634 
3635 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3636   std::string Code = R"(
3637     struct Lookup {
3638       int x;
3639     };
3640 
3641     void target(Lookup val, bool b) {
3642       const Lookup* l = nullptr;
3643       while (b) {
3644         l = &val;
3645         /*[[p-inner]]*/
3646       }
3647       (void)0;
3648       /*[[p-outer]]*/
3649     }
3650   )";
3651   // The key property that we are verifying is implicit in `runDataflow` --
3652   // namely, that the analysis succeeds, rather than hitting the maximum number
3653   // of iterations.
3654   runDataflow(
3655       Code,
3656       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3657          ASTContext &ASTCtx) {
3658         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
3659         const Environment &InnerEnv =
3660             getEnvironmentAtAnnotation(Results, "p-inner");
3661         const Environment &OuterEnv =
3662             getEnvironmentAtAnnotation(Results, "p-outer");
3663 
3664         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3665         ASSERT_THAT(ValDecl, NotNull());
3666 
3667         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3668         ASSERT_THAT(LDecl, NotNull());
3669 
3670         // Inner.
3671         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
3672         ASSERT_THAT(LVal, NotNull());
3673 
3674         EXPECT_EQ(&LVal->getPointeeLoc(),
3675                   InnerEnv.getStorageLocation(*ValDecl));
3676 
3677         // Outer.
3678         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
3679         ASSERT_THAT(LVal, NotNull());
3680 
3681         // The loop body may not have been executed, so we should not conclude
3682         // that `l` points to `val`.
3683         EXPECT_NE(&LVal->getPointeeLoc(),
3684                   OuterEnv.getStorageLocation(*ValDecl));
3685       });
3686 }
3687 
3688 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
3689   std::string Code = R"(
3690     union Union {
3691       int A;
3692       float B;
3693     };
3694 
3695     void foo() {
3696       Union A;
3697       Union B;
3698       A = B;
3699     }
3700   )";
3701   // This is a crash regression test when calling the transfer function on a
3702   // `CXXThisExpr` that refers to a union.
3703   runDataflow(
3704       Code,
3705       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3706          ASTContext &) {},
3707       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3708 }
3709 
3710 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3711   std::string Code = R"(
3712     struct A {
3713       int Foo;
3714       int Bar;
3715     };
3716 
3717     void target() {
3718       int Qux;
3719       A Baz;
3720       Baz.Foo = Qux;
3721       auto &FooRef = Baz.Foo;
3722       auto &BarRef = Baz.Bar;
3723       auto &[BoundFooRef, BoundBarRef] = Baz;
3724       // [[p]]
3725     }
3726   )";
3727   runDataflow(
3728       Code,
3729       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3730          ASTContext &ASTCtx) {
3731         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3732         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3733 
3734         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3735         ASSERT_THAT(FooRefDecl, NotNull());
3736 
3737         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3738         ASSERT_THAT(BarRefDecl, NotNull());
3739 
3740         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3741         ASSERT_THAT(QuxDecl, NotNull());
3742 
3743         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3744         ASSERT_THAT(BoundFooRefDecl, NotNull());
3745 
3746         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3747         ASSERT_THAT(BoundBarRefDecl, NotNull());
3748 
3749         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3750         ASSERT_THAT(FooRefLoc, NotNull());
3751 
3752         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3753         ASSERT_THAT(BarRefLoc, NotNull());
3754 
3755         const Value *QuxVal = Env.getValue(*QuxDecl);
3756         ASSERT_THAT(QuxVal, NotNull());
3757 
3758         const StorageLocation *BoundFooRefLoc =
3759             Env.getStorageLocation(*BoundFooRefDecl);
3760         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3761 
3762         const StorageLocation *BoundBarRefLoc =
3763             Env.getStorageLocation(*BoundBarRefDecl);
3764         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3765 
3766         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
3767       });
3768 }
3769 
3770 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3771   std::string Code = R"(
3772     struct A {
3773       int &Foo;
3774       int &Bar;
3775     };
3776 
3777     void target(A Baz) {
3778       int Qux;
3779       Baz.Foo = Qux;
3780       auto &FooRef = Baz.Foo;
3781       auto &BarRef = Baz.Bar;
3782       auto &[BoundFooRef, BoundBarRef] = Baz;
3783       // [[p]]
3784     }
3785   )";
3786   runDataflow(
3787       Code,
3788       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3789          ASTContext &ASTCtx) {
3790         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3791         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3792 
3793         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3794         ASSERT_THAT(FooRefDecl, NotNull());
3795 
3796         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3797         ASSERT_THAT(BarRefDecl, NotNull());
3798 
3799         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3800         ASSERT_THAT(QuxDecl, NotNull());
3801 
3802         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3803         ASSERT_THAT(BoundFooRefDecl, NotNull());
3804 
3805         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3806         ASSERT_THAT(BoundBarRefDecl, NotNull());
3807 
3808         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3809         ASSERT_THAT(FooRefLoc, NotNull());
3810 
3811         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3812         ASSERT_THAT(BarRefLoc, NotNull());
3813 
3814         const Value *QuxVal = Env.getValue(*QuxDecl);
3815         ASSERT_THAT(QuxVal, NotNull());
3816 
3817         const StorageLocation *BoundFooRefLoc =
3818             Env.getStorageLocation(*BoundFooRefDecl);
3819         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3820 
3821         const StorageLocation *BoundBarRefLoc =
3822             Env.getStorageLocation(*BoundBarRefDecl);
3823         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3824 
3825         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
3826       });
3827 }
3828 
3829 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
3830   std::string Code = R"(
3831     struct A {
3832       int Foo;
3833       int Bar;
3834     };
3835 
3836     void target() {
3837       int Qux;
3838       A Baz;
3839       Baz.Foo = Qux;
3840       auto &FooRef = Baz.Foo;
3841       auto &BarRef = Baz.Bar;
3842       auto [BoundFoo, BoundBar] = Baz;
3843       // [[p]]
3844     }
3845   )";
3846   runDataflow(
3847       Code,
3848       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3849          ASTContext &ASTCtx) {
3850         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3851         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3852 
3853         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3854         ASSERT_THAT(FooRefDecl, NotNull());
3855 
3856         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3857         ASSERT_THAT(BarRefDecl, NotNull());
3858 
3859         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3860         ASSERT_THAT(BoundFooDecl, NotNull());
3861 
3862         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3863         ASSERT_THAT(BoundBarDecl, NotNull());
3864 
3865         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3866         ASSERT_THAT(QuxDecl, NotNull());
3867 
3868         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3869         ASSERT_THAT(FooRefLoc, NotNull());
3870 
3871         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3872         ASSERT_THAT(BarRefLoc, NotNull());
3873 
3874         const Value *QuxVal = Env.getValue(*QuxDecl);
3875         ASSERT_THAT(QuxVal, NotNull());
3876 
3877         const StorageLocation *BoundFooLoc =
3878             Env.getStorageLocation(*BoundFooDecl);
3879         EXPECT_NE(BoundFooLoc, FooRefLoc);
3880 
3881         const StorageLocation *BoundBarLoc =
3882             Env.getStorageLocation(*BoundBarDecl);
3883         EXPECT_NE(BoundBarLoc, BarRefLoc);
3884 
3885         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
3886       });
3887 }
3888 
3889 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
3890   std::string Code = R"(
3891     namespace std {
3892     using size_t = int;
3893     template <class> struct tuple_size;
3894     template <std::size_t, class> struct tuple_element;
3895     template <class...> class tuple;
3896 
3897     namespace {
3898     template <class T, T v>
3899     struct size_helper { static const T value = v; };
3900     } // namespace
3901 
3902     template <class... T>
3903     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
3904 
3905     template <std::size_t I, class... T>
3906     struct tuple_element<I, tuple<T...>> {
3907       using type =  __type_pack_element<I, T...>;
3908     };
3909 
3910     template <class...> class tuple {};
3911 
3912     template <std::size_t I, class... T>
3913     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
3914     } // namespace std
3915 
3916     std::tuple<bool, int> makeTuple();
3917 
3918     void target(bool B) {
3919       auto [BoundFoo, BoundBar] = makeTuple();
3920       bool Baz;
3921       // Include if-then-else to test interaction of `BindingDecl` with join.
3922       if (B) {
3923         Baz = BoundFoo;
3924         (void)BoundBar;
3925         // [[p1]]
3926       } else {
3927         Baz = BoundFoo;
3928       }
3929       (void)0;
3930       // [[p2]]
3931     }
3932   )";
3933   runDataflow(
3934       Code,
3935       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3936          ASTContext &ASTCtx) {
3937         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
3938         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
3939 
3940         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3941         ASSERT_THAT(BoundFooDecl, NotNull());
3942 
3943         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3944         ASSERT_THAT(BoundBarDecl, NotNull());
3945 
3946         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3947         ASSERT_THAT(BazDecl, NotNull());
3948 
3949         // BindingDecls always map to references -- either lvalue or rvalue, so
3950         // we still need to skip here.
3951         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
3952         ASSERT_THAT(BoundFooValue, NotNull());
3953         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
3954 
3955         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
3956         ASSERT_THAT(BoundBarValue, NotNull());
3957         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
3958 
3959         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
3960         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
3961 
3962         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
3963 
3964         // Test that `BoundFooDecl` retains the value we expect, after the join.
3965         BoundFooValue = Env2.getValue(*BoundFooDecl);
3966         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
3967       });
3968 }
3969 
3970 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
3971   std::string Code = R"(
3972     namespace std {
3973     using size_t = int;
3974     template <class> struct tuple_size;
3975     template <std::size_t, class> struct tuple_element;
3976     template <class...> class tuple;
3977 
3978     namespace {
3979     template <class T, T v>
3980     struct size_helper { static const T value = v; };
3981     } // namespace
3982 
3983     template <class... T>
3984     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
3985 
3986     template <std::size_t I, class... T>
3987     struct tuple_element<I, tuple<T...>> {
3988       using type =  __type_pack_element<I, T...>;
3989     };
3990 
3991     template <class...> class tuple {};
3992 
3993     template <std::size_t I, class... T>
3994     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
3995     } // namespace std
3996 
3997     std::tuple<bool, int> &getTuple();
3998 
3999     void target(bool B) {
4000       auto &[BoundFoo, BoundBar] = getTuple();
4001       bool Baz;
4002       // Include if-then-else to test interaction of `BindingDecl` with join.
4003       if (B) {
4004         Baz = BoundFoo;
4005         (void)BoundBar;
4006         // [[p1]]
4007       } else {
4008         Baz = BoundFoo;
4009       }
4010       (void)0;
4011       // [[p2]]
4012     }
4013   )";
4014   runDataflow(
4015       Code,
4016       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4017          ASTContext &ASTCtx) {
4018         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4019         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4020 
4021         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4022         ASSERT_THAT(BoundFooDecl, NotNull());
4023 
4024         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4025         ASSERT_THAT(BoundBarDecl, NotNull());
4026 
4027         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4028         ASSERT_THAT(BazDecl, NotNull());
4029 
4030         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4031         ASSERT_THAT(BoundFooValue, NotNull());
4032         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4033 
4034         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4035         ASSERT_THAT(BoundBarValue, NotNull());
4036         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4037 
4038         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4039         // works as expected. We don't test aliasing properties of the
4040         // reference, because we don't model `std::get` and so have no way to
4041         // equate separate references into the tuple.
4042         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4043 
4044         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4045 
4046         // Test that `BoundFooDecl` retains the value we expect, after the join.
4047         BoundFooValue = Env2.getValue(*BoundFooDecl);
4048         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4049       });
4050 }
4051 
4052 TEST(TransferTest, BinaryOperatorComma) {
4053   std::string Code = R"(
4054     void target(int Foo, int Bar) {
4055       int &Baz = (Foo, Bar);
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 *BarDecl = findValueDecl(ASTCtx, "Bar");
4067         ASSERT_THAT(BarDecl, NotNull());
4068 
4069         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4070         ASSERT_THAT(BazDecl, NotNull());
4071 
4072         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4073         ASSERT_THAT(BarLoc, NotNull());
4074 
4075         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4076         EXPECT_EQ(BazLoc, BarLoc);
4077       });
4078 }
4079 
4080 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4081   std::string Code = R"(
4082     void target(bool Foo) {
4083       if (Foo) {
4084         (void)0;
4085         // [[if_then]]
4086       } else {
4087         (void)0;
4088         // [[if_else]]
4089       }
4090     }
4091   )";
4092   runDataflow(
4093       Code,
4094       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4095          ASTContext &ASTCtx) {
4096         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4097         const Environment &ThenEnv =
4098             getEnvironmentAtAnnotation(Results, "if_then");
4099         const Environment &ElseEnv =
4100             getEnvironmentAtAnnotation(Results, "if_else");
4101 
4102         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4103         ASSERT_THAT(FooDecl, NotNull());
4104 
4105         BoolValue &ThenFooVal = *cast<BoolValue>(ThenEnv.getValue(*FooDecl));
4106         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
4107 
4108         BoolValue &ElseFooVal = *cast<BoolValue>(ElseEnv.getValue(*FooDecl));
4109         EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
4110       });
4111 }
4112 
4113 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4114   std::string Code = R"(
4115     void target(bool Foo) {
4116       while (Foo) {
4117         (void)0;
4118         // [[loop_body]]
4119       }
4120       (void)0;
4121       // [[after_loop]]
4122     }
4123   )";
4124   runDataflow(
4125       Code,
4126       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4127          ASTContext &ASTCtx) {
4128         ASSERT_THAT(Results.keys(),
4129                     UnorderedElementsAre("loop_body", "after_loop"));
4130         const Environment &LoopBodyEnv =
4131             getEnvironmentAtAnnotation(Results, "loop_body");
4132         const Environment &AfterLoopEnv =
4133             getEnvironmentAtAnnotation(Results, "after_loop");
4134 
4135         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4136         ASSERT_THAT(FooDecl, NotNull());
4137 
4138         BoolValue &LoopBodyFooVal =
4139             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4140         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4141 
4142         BoolValue &AfterLoopFooVal =
4143             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl));
4144         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4145             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4146       });
4147 }
4148 
4149 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4150   std::string Code = R"(
4151     void target(bool Foo) {
4152       bool Bar = true;
4153       do {
4154         (void)0;
4155         // [[loop_body]]
4156         Bar = false;
4157       } while (Foo);
4158       (void)0;
4159       // [[after_loop]]
4160     }
4161   )";
4162   runDataflow(
4163       Code,
4164       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4165          ASTContext &ASTCtx) {
4166         ASSERT_THAT(Results.keys(),
4167                     UnorderedElementsAre("loop_body", "after_loop"));
4168         const Environment &LoopBodyEnv =
4169             getEnvironmentAtAnnotation(Results, "loop_body");
4170         const Environment &AfterLoopEnv =
4171             getEnvironmentAtAnnotation(Results, "after_loop");
4172 
4173         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4174         ASSERT_THAT(FooDecl, NotNull());
4175 
4176         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4177         ASSERT_THAT(BarDecl, NotNull());
4178 
4179         BoolValue &LoopBodyFooVal =
4180             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4181         BoolValue &LoopBodyBarVal =
4182             *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl));
4183         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
4184             LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4185 
4186         BoolValue &AfterLoopFooVal =
4187             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl));
4188         BoolValue &AfterLoopBarVal =
4189             *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl));
4190         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4191             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4192         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4193             AfterLoopEnv.makeNot(AfterLoopBarVal)));
4194       });
4195 }
4196 
4197 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4198   std::string Code = R"(
4199     void target(bool Foo) {
4200       for (; Foo;) {
4201         (void)0;
4202         // [[loop_body]]
4203       }
4204       (void)0;
4205       // [[after_loop]]
4206     }
4207   )";
4208   runDataflow(
4209       Code,
4210       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4211          ASTContext &ASTCtx) {
4212         ASSERT_THAT(Results.keys(),
4213                     UnorderedElementsAre("loop_body", "after_loop"));
4214         const Environment &LoopBodyEnv =
4215             getEnvironmentAtAnnotation(Results, "loop_body");
4216         const Environment &AfterLoopEnv =
4217             getEnvironmentAtAnnotation(Results, "after_loop");
4218 
4219         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4220         ASSERT_THAT(FooDecl, NotNull());
4221 
4222         BoolValue &LoopBodyFooVal =
4223             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4224         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4225 
4226         BoolValue &AfterLoopFooVal =
4227             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl));
4228         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4229             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4230       });
4231 }
4232 
4233 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4234   std::string Code = R"(
4235     void target(bool Foo) {
4236       for (;;) {
4237         (void)0;
4238         // [[loop_body]]
4239       }
4240     }
4241   )";
4242   runDataflow(
4243       Code,
4244       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4245          ASTContext &ASTCtx) {
4246         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4247         const Environment &LoopBodyEnv =
4248             getEnvironmentAtAnnotation(Results, "loop_body");
4249 
4250         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4251         ASSERT_THAT(FooDecl, NotNull());
4252 
4253         BoolValue &LoopBodyFooVal =
4254             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4255         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4256       });
4257 }
4258 
4259 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4260   std::string Code = R"(
4261     bool GiveBool();
4262     void SetBool(bool &Var) { Var = true; }
4263 
4264     void target() {
4265       bool Foo = GiveBool();
4266       SetBool(Foo);
4267       // [[p]]
4268     }
4269   )";
4270   runDataflow(
4271       Code,
4272       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4273          ASTContext &ASTCtx) {
4274         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4275         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4276 
4277         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4278         ASSERT_THAT(FooDecl, NotNull());
4279 
4280         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4281         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4282         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4283       },
4284       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4285 }
4286 
4287 TEST(TransferTest, ContextSensitiveReturnReference) {
4288   std::string Code = R"(
4289     class S {};
4290     S& target(bool b, S &s) {
4291       return s;
4292       // [[p]]
4293     }
4294   )";
4295   runDataflow(
4296       Code,
4297       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4298          ASTContext &ASTCtx) {
4299         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4300 
4301         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4302         ASSERT_THAT(SDecl, NotNull());
4303 
4304         auto *SLoc = Env.getStorageLocation(*SDecl);
4305         ASSERT_THAT(SLoc, NotNull());
4306 
4307         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4308       },
4309       {BuiltinOptions{ContextSensitiveOptions{}}});
4310 }
4311 
4312 // This test is a regression test, based on a real crash.
4313 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4314   std::string Code = R"(
4315     class S {};
4316     S& target(bool b, S &s) {
4317       return b ? s : s;
4318       // [[p]]
4319     }
4320   )";
4321   runDataflow(
4322       Code,
4323       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4324          ASTContext &ASTCtx) {
4325         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4326         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4327 
4328         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4329         ASSERT_THAT(SDecl, NotNull());
4330 
4331         auto *SLoc = Env.getStorageLocation(*SDecl);
4332         ASSERT_THAT(SLoc, NotNull());
4333         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4334 
4335         auto *Loc = Env.getReturnStorageLocation();
4336         ASSERT_THAT(Loc, NotNull());
4337         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4338 
4339         // TODO: We would really like to make this stronger assertion, but that
4340         // doesn't work because we don't propagate values correctly through
4341         // the conditional operator yet.
4342         // ASSERT_THAT(Loc, Eq(SLoc));
4343       },
4344       {BuiltinOptions{ContextSensitiveOptions{}}});
4345 }
4346 
4347 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4348   std::string Code = R"(
4349     class S {};
4350     S &callee(bool b, S &s1_parm, S &s2_parm) {
4351       if (b)
4352         return s1_parm;
4353       else
4354         return s2_parm;
4355     }
4356     void target(bool b) {
4357       S s1;
4358       S s2;
4359       S &return_s1 = s1;
4360       S &return_s2 = s2;
4361       S &return_dont_know = callee(b, s1, s2);
4362       // [[p]]
4363     }
4364   )";
4365   runDataflow(
4366       Code,
4367       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4368          ASTContext &ASTCtx) {
4369         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4370 
4371         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4372         ASSERT_THAT(S1, NotNull());
4373         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4374         ASSERT_THAT(S2, NotNull());
4375         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4376         ASSERT_THAT(ReturnS1, NotNull());
4377         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4378         ASSERT_THAT(ReturnS2, NotNull());
4379         const ValueDecl *ReturnDontKnow =
4380             findValueDecl(ASTCtx, "return_dont_know");
4381         ASSERT_THAT(ReturnDontKnow, NotNull());
4382 
4383         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4384         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4385 
4386         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4387         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4388 
4389         // In the case where we don't have a consistent storage location for
4390         // the return value, the framework creates a new storage location, which
4391         // should be different from the storage locations of `s1` and `s2`.
4392         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4393         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4394       },
4395       {BuiltinOptions{ContextSensitiveOptions{}}});
4396 }
4397 
4398 TEST(TransferTest, ContextSensitiveDepthZero) {
4399   std::string Code = R"(
4400     bool GiveBool();
4401     void SetBool(bool &Var) { Var = true; }
4402 
4403     void target() {
4404       bool Foo = GiveBool();
4405       SetBool(Foo);
4406       // [[p]]
4407     }
4408   )";
4409   runDataflow(
4410       Code,
4411       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4412          ASTContext &ASTCtx) {
4413         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4414         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4415 
4416         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4417         ASSERT_THAT(FooDecl, NotNull());
4418 
4419         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4420         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4421         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4422       },
4423       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4424 }
4425 
4426 TEST(TransferTest, ContextSensitiveSetTrue) {
4427   std::string Code = R"(
4428     bool GiveBool();
4429     void SetBool(bool &Var) { Var = true; }
4430 
4431     void target() {
4432       bool Foo = GiveBool();
4433       SetBool(Foo);
4434       // [[p]]
4435     }
4436   )";
4437   runDataflow(
4438       Code,
4439       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4440          ASTContext &ASTCtx) {
4441         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4442         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4443 
4444         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4445         ASSERT_THAT(FooDecl, NotNull());
4446 
4447         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4448         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4449       },
4450       {BuiltinOptions{ContextSensitiveOptions{}}});
4451 }
4452 
4453 TEST(TransferTest, ContextSensitiveSetFalse) {
4454   std::string Code = R"(
4455     bool GiveBool();
4456     void SetBool(bool &Var) { Var = false; }
4457 
4458     void target() {
4459       bool Foo = GiveBool();
4460       SetBool(Foo);
4461       // [[p]]
4462     }
4463   )";
4464   runDataflow(
4465       Code,
4466       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4467          ASTContext &ASTCtx) {
4468         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4469         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4470 
4471         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4472         ASSERT_THAT(FooDecl, NotNull());
4473 
4474         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4475         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4476       },
4477       {BuiltinOptions{ContextSensitiveOptions{}}});
4478 }
4479 
4480 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4481   std::string Code = R"(
4482     bool GiveBool();
4483     void SetBool(bool &Var, bool Val) { Var = Val; }
4484 
4485     void target() {
4486       bool Foo = GiveBool();
4487       bool Bar = GiveBool();
4488       SetBool(Foo, true);
4489       SetBool(Bar, false);
4490       // [[p]]
4491     }
4492   )";
4493   runDataflow(
4494       Code,
4495       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4496          ASTContext &ASTCtx) {
4497         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4498         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4499 
4500         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4501         ASSERT_THAT(FooDecl, NotNull());
4502 
4503         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4504         ASSERT_THAT(BarDecl, NotNull());
4505 
4506         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4507         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4508         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4509 
4510         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
4511         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4512         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4513       },
4514       {BuiltinOptions{ContextSensitiveOptions{}}});
4515 }
4516 
4517 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4518   std::string Code = R"(
4519     bool GiveBool();
4520     void SetBool1(bool &Var) { Var = true; }
4521     void SetBool2(bool &Var) { SetBool1(Var); }
4522 
4523     void target() {
4524       bool Foo = GiveBool();
4525       SetBool2(Foo);
4526       // [[p]]
4527     }
4528   )";
4529   runDataflow(
4530       Code,
4531       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4532          ASTContext &ASTCtx) {
4533         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4534         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4535 
4536         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4537         ASSERT_THAT(FooDecl, NotNull());
4538 
4539         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4540         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4541         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4542       },
4543       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4544 }
4545 
4546 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4547   std::string Code = R"(
4548     bool GiveBool();
4549     void SetBool1(bool &Var) { Var = true; }
4550     void SetBool2(bool &Var) { SetBool1(Var); }
4551 
4552     void target() {
4553       bool Foo = GiveBool();
4554       SetBool2(Foo);
4555       // [[p]]
4556     }
4557   )";
4558   runDataflow(
4559       Code,
4560       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4561          ASTContext &ASTCtx) {
4562         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4563         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4564 
4565         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4566         ASSERT_THAT(FooDecl, NotNull());
4567 
4568         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4569         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4570       },
4571       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4572 }
4573 
4574 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4575   std::string Code = R"(
4576     bool GiveBool();
4577     void SetBool1(bool &Var) { Var = true; }
4578     void SetBool2(bool &Var) { SetBool1(Var); }
4579     void SetBool3(bool &Var) { SetBool2(Var); }
4580 
4581     void target() {
4582       bool Foo = GiveBool();
4583       SetBool3(Foo);
4584       // [[p]]
4585     }
4586   )";
4587   runDataflow(
4588       Code,
4589       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4590          ASTContext &ASTCtx) {
4591         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4592         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4593 
4594         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4595         ASSERT_THAT(FooDecl, NotNull());
4596 
4597         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4598         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4599         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4600       },
4601       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4602 }
4603 
4604 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4605   std::string Code = R"(
4606     bool GiveBool();
4607     void SetBool1(bool &Var) { Var = true; }
4608     void SetBool2(bool &Var) { SetBool1(Var); }
4609     void SetBool3(bool &Var) { SetBool2(Var); }
4610 
4611     void target() {
4612       bool Foo = GiveBool();
4613       SetBool3(Foo);
4614       // [[p]]
4615     }
4616   )";
4617   runDataflow(
4618       Code,
4619       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4620          ASTContext &ASTCtx) {
4621         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4622         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4623 
4624         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4625         ASSERT_THAT(FooDecl, NotNull());
4626 
4627         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4628         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4629       },
4630       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
4631 }
4632 
4633 TEST(TransferTest, ContextSensitiveMutualRecursion) {
4634   std::string Code = R"(
4635     bool Pong(bool X, bool Y);
4636 
4637     bool Ping(bool X, bool Y) {
4638       if (X) {
4639         return Y;
4640       } else {
4641         return Pong(!X, Y);
4642       }
4643     }
4644 
4645     bool Pong(bool X, bool Y) {
4646       if (Y) {
4647         return X;
4648       } else {
4649         return Ping(X, !Y);
4650       }
4651     }
4652 
4653     void target() {
4654       bool Foo = Ping(false, false);
4655       // [[p]]
4656     }
4657   )";
4658   runDataflow(
4659       Code,
4660       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4661          ASTContext &ASTCtx) {
4662         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4663         // The analysis doesn't crash...
4664         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4665 
4666         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4667         ASSERT_THAT(FooDecl, NotNull());
4668 
4669         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4670         // ... but it also can't prove anything here.
4671         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4672         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4673       },
4674       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
4675 }
4676 
4677 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
4678   std::string Code = R"(
4679     void SetBools(bool &Var1, bool &Var2) {
4680       Var1 = true;
4681       Var2 = false;
4682     }
4683 
4684     void target() {
4685       bool Foo = false;
4686       bool Bar = true;
4687       SetBools(Foo, Bar);
4688       // [[p]]
4689     }
4690   )";
4691   runDataflow(
4692       Code,
4693       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4694          ASTContext &ASTCtx) {
4695         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4696         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4697 
4698         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4699         ASSERT_THAT(FooDecl, NotNull());
4700 
4701         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4702         ASSERT_THAT(BarDecl, NotNull());
4703 
4704         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4705         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4706         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4707 
4708         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
4709         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4710         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4711       },
4712       {BuiltinOptions{ContextSensitiveOptions{}}});
4713 }
4714 
4715 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
4716   std::string Code = R"(
4717     void IfCond(bool Cond, bool &Then, bool &Else) {
4718       if (Cond) {
4719         Then = true;
4720       } else {
4721         Else = true;
4722       }
4723     }
4724 
4725     void target() {
4726       bool Foo = false;
4727       bool Bar = false;
4728       bool Baz = false;
4729       IfCond(Foo, Bar, Baz);
4730       // [[p]]
4731     }
4732   )";
4733   runDataflow(
4734       Code,
4735       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4736          ASTContext &ASTCtx) {
4737         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4738         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4739 
4740         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4741         ASSERT_THAT(BarDecl, NotNull());
4742 
4743         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4744         ASSERT_THAT(BazDecl, NotNull());
4745 
4746         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
4747         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4748         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4749 
4750         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl));
4751         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4752         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
4753       },
4754       {BuiltinOptions{ContextSensitiveOptions{}}});
4755 }
4756 
4757 TEST(TransferTest, ContextSensitiveReturnVoid) {
4758   std::string Code = R"(
4759     void Noop() { return; }
4760 
4761     void target() {
4762       Noop();
4763       // [[p]]
4764     }
4765   )";
4766   runDataflow(
4767       Code,
4768       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4769          ASTContext &ASTCtx) {
4770         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4771         // This just tests that the analysis doesn't crash.
4772       },
4773       {BuiltinOptions{ContextSensitiveOptions{}}});
4774 }
4775 
4776 TEST(TransferTest, ContextSensitiveReturnTrue) {
4777   std::string Code = R"(
4778     bool GiveBool() { return true; }
4779 
4780     void target() {
4781       bool Foo = GiveBool();
4782       // [[p]]
4783     }
4784   )";
4785   runDataflow(
4786       Code,
4787       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4788          ASTContext &ASTCtx) {
4789         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4790         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4791 
4792         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4793         ASSERT_THAT(FooDecl, NotNull());
4794 
4795         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4796         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4797       },
4798       {BuiltinOptions{ContextSensitiveOptions{}}});
4799 }
4800 
4801 TEST(TransferTest, ContextSensitiveReturnFalse) {
4802   std::string Code = R"(
4803     bool GiveBool() { return false; }
4804 
4805     void target() {
4806       bool Foo = GiveBool();
4807       // [[p]]
4808     }
4809   )";
4810   runDataflow(
4811       Code,
4812       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4813          ASTContext &ASTCtx) {
4814         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4815         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4816 
4817         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4818         ASSERT_THAT(FooDecl, NotNull());
4819 
4820         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4821         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4822       },
4823       {BuiltinOptions{ContextSensitiveOptions{}}});
4824 }
4825 
4826 TEST(TransferTest, ContextSensitiveReturnArg) {
4827   std::string Code = R"(
4828     bool GiveBool();
4829     bool GiveBack(bool Arg) { return Arg; }
4830 
4831     void target() {
4832       bool Foo = GiveBool();
4833       bool Bar = GiveBack(Foo);
4834       bool Baz = Foo == Bar;
4835       // [[p]]
4836     }
4837   )";
4838   runDataflow(
4839       Code,
4840       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4841          ASTContext &ASTCtx) {
4842         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4843         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4844 
4845         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4846         ASSERT_THAT(BazDecl, NotNull());
4847 
4848         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl));
4849         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4850       },
4851       {BuiltinOptions{ContextSensitiveOptions{}}});
4852 }
4853 
4854 TEST(TransferTest, ContextSensitiveReturnInt) {
4855   std::string Code = R"(
4856     int identity(int x) { return x; }
4857 
4858     void target() {
4859       int y = identity(42);
4860       // [[p]]
4861     }
4862   )";
4863   runDataflow(
4864       Code,
4865       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4866          ASTContext &ASTCtx) {
4867         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4868         // This just tests that the analysis doesn't crash.
4869       },
4870       {BuiltinOptions{ContextSensitiveOptions{}}});
4871 }
4872 
4873 TEST(TransferTest, ContextSensitiveMethodLiteral) {
4874   std::string Code = R"(
4875     class MyClass {
4876     public:
4877       bool giveBool() { return true; }
4878     };
4879 
4880     void target() {
4881       MyClass MyObj;
4882       bool Foo = MyObj.giveBool();
4883       // [[p]]
4884     }
4885   )";
4886   runDataflow(
4887       Code,
4888       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4889          ASTContext &ASTCtx) {
4890         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4891         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4892 
4893         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4894         ASSERT_THAT(FooDecl, NotNull());
4895 
4896         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4897         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4898       },
4899       {BuiltinOptions{ContextSensitiveOptions{}}});
4900 }
4901 
4902 TEST(TransferTest, ContextSensitiveMethodGetter) {
4903   std::string Code = R"(
4904     class MyClass {
4905     public:
4906       bool getField() { return Field; }
4907 
4908       bool Field;
4909     };
4910 
4911     void target() {
4912       MyClass MyObj;
4913       MyObj.Field = true;
4914       bool Foo = MyObj.getField();
4915       // [[p]]
4916     }
4917   )";
4918   runDataflow(
4919       Code,
4920       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4921          ASTContext &ASTCtx) {
4922         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4923         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4924 
4925         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4926         ASSERT_THAT(FooDecl, NotNull());
4927 
4928         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4929         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4930       },
4931       {BuiltinOptions{ContextSensitiveOptions{}}});
4932 }
4933 
4934 TEST(TransferTest, ContextSensitiveMethodSetter) {
4935   std::string Code = R"(
4936     class MyClass {
4937     public:
4938       void setField(bool Val) { Field = Val; }
4939 
4940       bool Field;
4941     };
4942 
4943     void target() {
4944       MyClass MyObj;
4945       MyObj.setField(true);
4946       bool Foo = MyObj.Field;
4947       // [[p]]
4948     }
4949   )";
4950   runDataflow(
4951       Code,
4952       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4953          ASTContext &ASTCtx) {
4954         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4955         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4956 
4957         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4958         ASSERT_THAT(FooDecl, NotNull());
4959 
4960         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4961         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4962       },
4963       {BuiltinOptions{ContextSensitiveOptions{}}});
4964 }
4965 
4966 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
4967   std::string Code = R"(
4968     class MyClass {
4969     public:
4970       bool getField() { return Field; }
4971       void setField(bool Val) { Field = Val; }
4972 
4973     private:
4974       bool Field;
4975     };
4976 
4977     void target() {
4978       MyClass MyObj;
4979       MyObj.setField(true);
4980       bool Foo = MyObj.getField();
4981       // [[p]]
4982     }
4983   )";
4984   runDataflow(
4985       Code,
4986       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4987          ASTContext &ASTCtx) {
4988         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4989         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4990 
4991         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4992         ASSERT_THAT(FooDecl, NotNull());
4993 
4994         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4995         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4996       },
4997       {BuiltinOptions{ContextSensitiveOptions{}}});
4998 }
4999 
5000 
5001 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5002   std::string Code = R"(
5003     class MyClass {
5004     public:
5005       void Inner() { MyField = true; }
5006       void Outer() { Inner(); }
5007 
5008       bool MyField;
5009     };
5010 
5011     void target() {
5012       MyClass MyObj;
5013       MyObj.Outer();
5014       bool Foo = MyObj.MyField;
5015       // [[p]]
5016     }
5017   )";
5018   runDataflow(
5019       Code,
5020       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5021          ASTContext &ASTCtx) {
5022         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5023         ;
5024         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5025 
5026         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5027         ASSERT_THAT(FooDecl, NotNull());
5028 
5029         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5030         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5031       },
5032       {BuiltinOptions{ContextSensitiveOptions{}}});
5033 }
5034 
5035 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5036   std::string Code = R"(
5037     class MyClass {
5038     public:
5039       bool Inner() { return MyField; }
5040       bool Outer() { return Inner(); }
5041 
5042       bool MyField;
5043     };
5044 
5045     void target() {
5046       MyClass MyObj;
5047       MyObj.MyField = true;
5048       bool Foo = MyObj.Outer();
5049       // [[p]]
5050     }
5051   )";
5052   runDataflow(
5053       Code,
5054       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5055          ASTContext &ASTCtx) {
5056         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5057         ;
5058         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5059 
5060         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5061         ASSERT_THAT(FooDecl, NotNull());
5062 
5063         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5064         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5065       },
5066       {BuiltinOptions{ContextSensitiveOptions{}}});
5067 }
5068 
5069 TEST(TransferTest, ContextSensitiveConstructorBody) {
5070   std::string Code = R"(
5071     class MyClass {
5072     public:
5073       MyClass() { MyField = true; }
5074 
5075       bool MyField;
5076     };
5077 
5078     void target() {
5079       MyClass MyObj;
5080       bool Foo = MyObj.MyField;
5081       // [[p]]
5082     }
5083   )";
5084   runDataflow(
5085       Code,
5086       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5087          ASTContext &ASTCtx) {
5088         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5089         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5090 
5091         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5092         ASSERT_THAT(FooDecl, NotNull());
5093 
5094         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5095         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5096       },
5097       {BuiltinOptions{ContextSensitiveOptions{}}});
5098 }
5099 
5100 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5101   std::string Code = R"(
5102     class MyClass {
5103     public:
5104       MyClass() : MyField(true) {}
5105 
5106       bool MyField;
5107     };
5108 
5109     void target() {
5110       MyClass MyObj;
5111       bool Foo = MyObj.MyField;
5112       // [[p]]
5113     }
5114   )";
5115   runDataflow(
5116       Code,
5117       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5118          ASTContext &ASTCtx) {
5119         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5120         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5121 
5122         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5123         ASSERT_THAT(FooDecl, NotNull());
5124 
5125         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5126         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5127       },
5128       {BuiltinOptions{ContextSensitiveOptions{}}});
5129 }
5130 
5131 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5132   std::string Code = R"(
5133     class MyClass {
5134     public:
5135       MyClass() = default;
5136 
5137       bool MyField = true;
5138     };
5139 
5140     void target() {
5141       MyClass MyObj;
5142       bool Foo = MyObj.MyField;
5143       // [[p]]
5144     }
5145   )";
5146   runDataflow(
5147       Code,
5148       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5149          ASTContext &ASTCtx) {
5150         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5151         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5152 
5153         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5154         ASSERT_THAT(FooDecl, NotNull());
5155 
5156         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5157         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5158       },
5159       {BuiltinOptions{ContextSensitiveOptions{}}});
5160 }
5161 
5162 TEST(TransferTest, UnnamedBitfieldInitializer) {
5163   std::string Code = R"(
5164     struct B {};
5165     struct A {
5166       unsigned a;
5167       unsigned : 4;
5168       unsigned c;
5169       B b;
5170     };
5171     void target() {
5172       A a = {};
5173       A test = a;
5174       (void)test.c;
5175     }
5176   )";
5177   runDataflow(
5178       Code,
5179       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5180          ASTContext &ASTCtx) {
5181         // This doesn't need a body because this test was crashing the framework
5182         // before handling correctly Unnamed bitfields in `InitListExpr`.
5183       });
5184 }
5185 
5186 // Repro for a crash that used to occur with chained short-circuiting logical
5187 // operators.
5188 TEST(TransferTest, ChainedLogicalOps) {
5189   std::string Code = R"(
5190     bool target() {
5191       bool b = true || false || false || false;
5192       // [[p]]
5193       return b;
5194     }
5195   )";
5196   runDataflow(
5197       Code,
5198       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5199          ASTContext &ASTCtx) {
5200         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5201         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
5202         EXPECT_TRUE(Env.flowConditionImplies(B));
5203       });
5204 }
5205 
5206 // Repro for a crash that used to occur when we call a `noreturn` function
5207 // within one of the operands of a `&&` or `||` operator.
5208 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5209   std::string Code = R"(
5210     __attribute__((noreturn)) int doesnt_return();
5211     bool some_condition();
5212     void target(bool b1, bool b2) {
5213       // Neither of these should crash. In addition, if we don't terminate the
5214       // program, we know that the operators need to trigger the short-circuit
5215       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5216       // will be true.
5217       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5218       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5219 
5220       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5221       // entire expression unreachable. So we know that in both of the following
5222       // cases, if `target()` terminates, the `else` branch was taken.
5223       bool NoreturnOnLhsMakesAndUnreachable = false;
5224       if (some_condition())
5225          doesnt_return() > 0 && some_condition();
5226       else
5227          NoreturnOnLhsMakesAndUnreachable = true;
5228 
5229       bool NoreturnOnLhsMakesOrUnreachable = false;
5230       if (some_condition())
5231          doesnt_return() > 0 || some_condition();
5232       else
5233          NoreturnOnLhsMakesOrUnreachable = true;
5234 
5235       // [[p]]
5236     }
5237   )";
5238   runDataflow(
5239       Code,
5240       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5241          ASTContext &ASTCtx) {
5242         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5243         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5244 
5245         // Check that [[p]] is reachable with a non-false flow condition.
5246         EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false)));
5247 
5248         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1");
5249         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(B1)));
5250 
5251         auto &NoreturnOnRhsOfAnd =
5252             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd");
5253         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(NoreturnOnRhsOfAnd)));
5254 
5255         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2");
5256         EXPECT_TRUE(Env.flowConditionImplies(B2));
5257 
5258         auto &NoreturnOnRhsOfOr =
5259             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr");
5260         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr));
5261 
5262         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5263             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable");
5264         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable));
5265 
5266         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5267             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable");
5268         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable));
5269       });
5270 }
5271 
5272 TEST(TransferTest, NewExpressions) {
5273   std::string Code = R"(
5274     void target() {
5275       int *p = new int(42);
5276       // [[after_new]]
5277     }
5278   )";
5279   runDataflow(
5280       Code,
5281       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5282          ASTContext &ASTCtx) {
5283         const Environment &Env =
5284             getEnvironmentAtAnnotation(Results, "after_new");
5285 
5286         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5287 
5288         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5289       });
5290 }
5291 
5292 TEST(TransferTest, NewExpressions_Structs) {
5293   std::string Code = R"(
5294     struct Inner {
5295       int InnerField;
5296     };
5297 
5298     struct Outer {
5299       Inner OuterField;
5300     };
5301 
5302     void target() {
5303       Outer *p = new Outer;
5304       // Access the fields to make sure the analysis actually generates children
5305       // for them in the `AggregateStorageLoc` and `StructValue`.
5306       p->OuterField.InnerField;
5307       // [[after_new]]
5308     }
5309   )";
5310   runDataflow(
5311       Code,
5312       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5313          ASTContext &ASTCtx) {
5314         const Environment &Env =
5315             getEnvironmentAtAnnotation(Results, "after_new");
5316 
5317         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5318         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5319 
5320         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5321 
5322         auto &OuterLoc = cast<AggregateStorageLocation>(P.getPointeeLoc());
5323         auto &OuterFieldLoc =
5324             cast<AggregateStorageLocation>(OuterLoc.getChild(*OuterField));
5325         auto &InnerFieldLoc = OuterFieldLoc.getChild(*InnerField);
5326 
5327         // Values for the struct and all fields exist after the new.
5328         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5329         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5330         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5331       });
5332 }
5333 
5334 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5335   std::string Code = R"(
5336     struct A { static void static_member_func(); };
5337     void target() {
5338       // To check that we're treating function-to-pointer decay correctly,
5339       // create two pointers, then verify they refer to the same storage
5340       // location.
5341       // We need to do the test this way because even if an initializer (in this
5342       // case, the function-to-pointer decay) does not create a value, we still
5343       // create a value for the variable.
5344       void (*non_member_p1)() = target;
5345       void (*non_member_p2)() = target;
5346 
5347       // Do the same thing but for a static member function.
5348       void (*member_p1)() = A::static_member_func;
5349       void (*member_p2)() = A::static_member_func;
5350       // [[p]]
5351     }
5352   )";
5353   runDataflow(
5354       Code,
5355       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5356          ASTContext &ASTCtx) {
5357         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5358 
5359         auto &NonMemberP1 =
5360             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
5361         auto &NonMemberP2 =
5362             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
5363         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
5364 
5365         auto &MemberP1 =
5366             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
5367         auto &MemberP2 =
5368             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
5369         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
5370       });
5371 }
5372 
5373 // Check that the pointer that a builtin function decays to is associated with
5374 // a value.
5375 TEST(TransferTest, BuiltinFunctionModeled) {
5376   std::string Code = R"(
5377     void target() {
5378       __builtin_expect(0, 0);
5379       // [[p]]
5380     }
5381   )";
5382   runDataflow(
5383       Code,
5384       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5385          ASTContext &ASTCtx) {
5386         using ast_matchers::selectFirst;
5387         using ast_matchers::match;
5388         using ast_matchers::traverse;
5389         using ast_matchers::implicitCastExpr;
5390         using ast_matchers::hasCastKind;
5391 
5392         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5393 
5394         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
5395             "implicit_cast",
5396             match(traverse(TK_AsIs,
5397                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
5398                                .bind("implicit_cast")),
5399                   ASTCtx));
5400 
5401         ASSERT_THAT(ImplicitCast, NotNull());
5402         EXPECT_THAT(Env.getValueStrict(*ImplicitCast), NotNull());
5403       });
5404 }
5405 
5406 } // namespace
5407