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