xref: /freebsd/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
1*04eeddc0SDimitry Andric //===-- Transfer.cpp --------------------------------------------*- C++ -*-===//
2*04eeddc0SDimitry Andric //
3*04eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*04eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*04eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*04eeddc0SDimitry Andric //
7*04eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
8*04eeddc0SDimitry Andric //
9*04eeddc0SDimitry Andric //  This file defines transfer functions that evaluate program statements and
10*04eeddc0SDimitry Andric //  update an environment accordingly.
11*04eeddc0SDimitry Andric //
12*04eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
13*04eeddc0SDimitry Andric 
14*04eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/Transfer.h"
15*04eeddc0SDimitry Andric #include "clang/AST/Decl.h"
16*04eeddc0SDimitry Andric #include "clang/AST/DeclBase.h"
17*04eeddc0SDimitry Andric #include "clang/AST/DeclCXX.h"
18*04eeddc0SDimitry Andric #include "clang/AST/Expr.h"
19*04eeddc0SDimitry Andric #include "clang/AST/ExprCXX.h"
20*04eeddc0SDimitry Andric #include "clang/AST/OperationKinds.h"
21*04eeddc0SDimitry Andric #include "clang/AST/Stmt.h"
22*04eeddc0SDimitry Andric #include "clang/AST/StmtVisitor.h"
23*04eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
24*04eeddc0SDimitry Andric #include "clang/Basic/OperatorKinds.h"
25*04eeddc0SDimitry Andric #include "llvm/ADT/STLExtras.h"
26*04eeddc0SDimitry Andric #include "llvm/Support/Casting.h"
27*04eeddc0SDimitry Andric #include <cassert>
28*04eeddc0SDimitry Andric #include <memory>
29*04eeddc0SDimitry Andric #include <tuple>
30*04eeddc0SDimitry Andric 
31*04eeddc0SDimitry Andric namespace clang {
32*04eeddc0SDimitry Andric namespace dataflow {
33*04eeddc0SDimitry Andric 
34*04eeddc0SDimitry Andric static const Expr *skipExprWithCleanups(const Expr *E) {
35*04eeddc0SDimitry Andric   if (auto *C = dyn_cast_or_null<ExprWithCleanups>(E))
36*04eeddc0SDimitry Andric     return C->getSubExpr();
37*04eeddc0SDimitry Andric   return E;
38*04eeddc0SDimitry Andric }
39*04eeddc0SDimitry Andric 
40*04eeddc0SDimitry Andric class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
41*04eeddc0SDimitry Andric public:
42*04eeddc0SDimitry Andric   TransferVisitor(Environment &Env) : Env(Env) {}
43*04eeddc0SDimitry Andric 
44*04eeddc0SDimitry Andric   void VisitBinaryOperator(const BinaryOperator *S) {
45*04eeddc0SDimitry Andric     if (S->getOpcode() == BO_Assign) {
46*04eeddc0SDimitry Andric       // The CFG does not contain `ParenExpr` as top-level statements in basic
47*04eeddc0SDimitry Andric       // blocks, however sub-expressions can still be of that type.
48*04eeddc0SDimitry Andric       assert(S->getLHS() != nullptr);
49*04eeddc0SDimitry Andric       const Expr *LHS = S->getLHS()->IgnoreParens();
50*04eeddc0SDimitry Andric 
51*04eeddc0SDimitry Andric       assert(LHS != nullptr);
52*04eeddc0SDimitry Andric       auto *LHSLoc = Env.getStorageLocation(*LHS, SkipPast::Reference);
53*04eeddc0SDimitry Andric       if (LHSLoc == nullptr)
54*04eeddc0SDimitry Andric         return;
55*04eeddc0SDimitry Andric 
56*04eeddc0SDimitry Andric       // The CFG does not contain `ParenExpr` as top-level statements in basic
57*04eeddc0SDimitry Andric       // blocks, however sub-expressions can still be of that type.
58*04eeddc0SDimitry Andric       assert(S->getRHS() != nullptr);
59*04eeddc0SDimitry Andric       const Expr *RHS = S->getRHS()->IgnoreParens();
60*04eeddc0SDimitry Andric 
61*04eeddc0SDimitry Andric       assert(RHS != nullptr);
62*04eeddc0SDimitry Andric       Value *RHSVal = Env.getValue(*RHS, SkipPast::Reference);
63*04eeddc0SDimitry Andric       if (RHSVal == nullptr)
64*04eeddc0SDimitry Andric         return;
65*04eeddc0SDimitry Andric 
66*04eeddc0SDimitry Andric       // Assign a value to the storage location of the left-hand side.
67*04eeddc0SDimitry Andric       Env.setValue(*LHSLoc, *RHSVal);
68*04eeddc0SDimitry Andric 
69*04eeddc0SDimitry Andric       // Assign a storage location for the whole expression.
70*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, *LHSLoc);
71*04eeddc0SDimitry Andric     }
72*04eeddc0SDimitry Andric     // FIXME: Add support for BO_EQ, BO_NE.
73*04eeddc0SDimitry Andric   }
74*04eeddc0SDimitry Andric 
75*04eeddc0SDimitry Andric   void VisitDeclRefExpr(const DeclRefExpr *S) {
76*04eeddc0SDimitry Andric     assert(S->getDecl() != nullptr);
77*04eeddc0SDimitry Andric     auto *DeclLoc = Env.getStorageLocation(*S->getDecl(), SkipPast::None);
78*04eeddc0SDimitry Andric     if (DeclLoc == nullptr)
79*04eeddc0SDimitry Andric       return;
80*04eeddc0SDimitry Andric 
81*04eeddc0SDimitry Andric     if (S->getDecl()->getType()->isReferenceType()) {
82*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, *DeclLoc);
83*04eeddc0SDimitry Andric     } else {
84*04eeddc0SDimitry Andric       auto &Loc = Env.createStorageLocation(*S);
85*04eeddc0SDimitry Andric       auto &Val = Env.takeOwnership(std::make_unique<ReferenceValue>(*DeclLoc));
86*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, Loc);
87*04eeddc0SDimitry Andric       Env.setValue(Loc, Val);
88*04eeddc0SDimitry Andric     }
89*04eeddc0SDimitry Andric   }
90*04eeddc0SDimitry Andric 
91*04eeddc0SDimitry Andric   void VisitDeclStmt(const DeclStmt *S) {
92*04eeddc0SDimitry Andric     // Group decls are converted into single decls in the CFG so the cast below
93*04eeddc0SDimitry Andric     // is safe.
94*04eeddc0SDimitry Andric     const auto &D = *cast<VarDecl>(S->getSingleDecl());
95*04eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(D);
96*04eeddc0SDimitry Andric     Env.setStorageLocation(D, Loc);
97*04eeddc0SDimitry Andric 
98*04eeddc0SDimitry Andric     const Expr *InitExpr = D.getInit();
99*04eeddc0SDimitry Andric     if (InitExpr == nullptr) {
100*04eeddc0SDimitry Andric       // No initializer expression - associate `Loc` with a new value.
101*04eeddc0SDimitry Andric       if (Value *Val = Env.createValue(D.getType()))
102*04eeddc0SDimitry Andric         Env.setValue(Loc, *Val);
103*04eeddc0SDimitry Andric       return;
104*04eeddc0SDimitry Andric     }
105*04eeddc0SDimitry Andric 
106*04eeddc0SDimitry Andric     // The CFG does not contain `ParenExpr` as top-level statements in basic
107*04eeddc0SDimitry Andric     // blocks, however sub-expressions can still be of that type.
108*04eeddc0SDimitry Andric     InitExpr = skipExprWithCleanups(D.getInit()->IgnoreParens());
109*04eeddc0SDimitry Andric     assert(InitExpr != nullptr);
110*04eeddc0SDimitry Andric 
111*04eeddc0SDimitry Andric     if (D.getType()->isReferenceType()) {
112*04eeddc0SDimitry Andric       // Initializing a reference variable - do not create a reference to
113*04eeddc0SDimitry Andric       // reference.
114*04eeddc0SDimitry Andric       if (auto *InitExprLoc =
115*04eeddc0SDimitry Andric               Env.getStorageLocation(*InitExpr, SkipPast::Reference)) {
116*04eeddc0SDimitry Andric         auto &Val =
117*04eeddc0SDimitry Andric             Env.takeOwnership(std::make_unique<ReferenceValue>(*InitExprLoc));
118*04eeddc0SDimitry Andric         Env.setValue(Loc, Val);
119*04eeddc0SDimitry Andric       } else {
120*04eeddc0SDimitry Andric         // FIXME: The initializer expression must always be assigned a value.
121*04eeddc0SDimitry Andric         // Replace this with an assert when we have sufficient coverage of
122*04eeddc0SDimitry Andric         // language features.
123*04eeddc0SDimitry Andric         if (Value *Val = Env.createValue(D.getType()))
124*04eeddc0SDimitry Andric           Env.setValue(Loc, *Val);
125*04eeddc0SDimitry Andric       }
126*04eeddc0SDimitry Andric       return;
127*04eeddc0SDimitry Andric     }
128*04eeddc0SDimitry Andric 
129*04eeddc0SDimitry Andric     if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) {
130*04eeddc0SDimitry Andric       Env.setValue(Loc, *InitExprVal);
131*04eeddc0SDimitry Andric     } else if (!D.getType()->isStructureOrClassType()) {
132*04eeddc0SDimitry Andric       // FIXME: The initializer expression must always be assigned a value.
133*04eeddc0SDimitry Andric       // Replace this with an assert when we have sufficient coverage of
134*04eeddc0SDimitry Andric       // language features.
135*04eeddc0SDimitry Andric       if (Value *Val = Env.createValue(D.getType()))
136*04eeddc0SDimitry Andric         Env.setValue(Loc, *Val);
137*04eeddc0SDimitry Andric     } else {
138*04eeddc0SDimitry Andric       llvm_unreachable("structs and classes must always be assigned values");
139*04eeddc0SDimitry Andric     }
140*04eeddc0SDimitry Andric   }
141*04eeddc0SDimitry Andric 
142*04eeddc0SDimitry Andric   void VisitImplicitCastExpr(const ImplicitCastExpr *S) {
143*04eeddc0SDimitry Andric     // The CFG does not contain `ParenExpr` as top-level statements in basic
144*04eeddc0SDimitry Andric     // blocks, however sub-expressions can still be of that type.
145*04eeddc0SDimitry Andric     assert(S->getSubExpr() != nullptr);
146*04eeddc0SDimitry Andric     const Expr *SubExpr = S->getSubExpr()->IgnoreParens();
147*04eeddc0SDimitry Andric     assert(SubExpr != nullptr);
148*04eeddc0SDimitry Andric 
149*04eeddc0SDimitry Andric     switch (S->getCastKind()) {
150*04eeddc0SDimitry Andric     case CK_LValueToRValue: {
151*04eeddc0SDimitry Andric       auto *SubExprVal = Env.getValue(*SubExpr, SkipPast::Reference);
152*04eeddc0SDimitry Andric       if (SubExprVal == nullptr)
153*04eeddc0SDimitry Andric         break;
154*04eeddc0SDimitry Andric 
155*04eeddc0SDimitry Andric       auto &ExprLoc = Env.createStorageLocation(*S);
156*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, ExprLoc);
157*04eeddc0SDimitry Andric       Env.setValue(ExprLoc, *SubExprVal);
158*04eeddc0SDimitry Andric       break;
159*04eeddc0SDimitry Andric     }
160*04eeddc0SDimitry Andric     case CK_NoOp: {
161*04eeddc0SDimitry Andric       // FIXME: Consider making `Environment::getStorageLocation` skip noop
162*04eeddc0SDimitry Andric       // expressions (this and other similar expressions in the file) instead of
163*04eeddc0SDimitry Andric       // assigning them storage locations.
164*04eeddc0SDimitry Andric       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
165*04eeddc0SDimitry Andric       if (SubExprLoc == nullptr)
166*04eeddc0SDimitry Andric         break;
167*04eeddc0SDimitry Andric 
168*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, *SubExprLoc);
169*04eeddc0SDimitry Andric       break;
170*04eeddc0SDimitry Andric     }
171*04eeddc0SDimitry Andric     default:
172*04eeddc0SDimitry Andric       // FIXME: Add support for CK_UserDefinedConversion,
173*04eeddc0SDimitry Andric       // CK_ConstructorConversion, CK_UncheckedDerivedToBase.
174*04eeddc0SDimitry Andric       break;
175*04eeddc0SDimitry Andric     }
176*04eeddc0SDimitry Andric   }
177*04eeddc0SDimitry Andric 
178*04eeddc0SDimitry Andric   void VisitUnaryOperator(const UnaryOperator *S) {
179*04eeddc0SDimitry Andric     // The CFG does not contain `ParenExpr` as top-level statements in basic
180*04eeddc0SDimitry Andric     // blocks, however sub-expressions can still be of that type.
181*04eeddc0SDimitry Andric     assert(S->getSubExpr() != nullptr);
182*04eeddc0SDimitry Andric     const Expr *SubExpr = S->getSubExpr()->IgnoreParens();
183*04eeddc0SDimitry Andric     assert(SubExpr != nullptr);
184*04eeddc0SDimitry Andric 
185*04eeddc0SDimitry Andric     switch (S->getOpcode()) {
186*04eeddc0SDimitry Andric     case UO_Deref: {
187*04eeddc0SDimitry Andric       // Skip past a reference to handle dereference of a dependent pointer.
188*04eeddc0SDimitry Andric       const auto *SubExprVal = cast_or_null<PointerValue>(
189*04eeddc0SDimitry Andric           Env.getValue(*SubExpr, SkipPast::Reference));
190*04eeddc0SDimitry Andric       if (SubExprVal == nullptr)
191*04eeddc0SDimitry Andric         break;
192*04eeddc0SDimitry Andric 
193*04eeddc0SDimitry Andric       auto &Loc = Env.createStorageLocation(*S);
194*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, Loc);
195*04eeddc0SDimitry Andric       Env.setValue(Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(
196*04eeddc0SDimitry Andric                             SubExprVal->getPointeeLoc())));
197*04eeddc0SDimitry Andric       break;
198*04eeddc0SDimitry Andric     }
199*04eeddc0SDimitry Andric     case UO_AddrOf: {
200*04eeddc0SDimitry Andric       // Do not form a pointer to a reference. If `SubExpr` is assigned a
201*04eeddc0SDimitry Andric       // `ReferenceValue` then form a value that points to the location of its
202*04eeddc0SDimitry Andric       // pointee.
203*04eeddc0SDimitry Andric       StorageLocation *PointeeLoc =
204*04eeddc0SDimitry Andric           Env.getStorageLocation(*SubExpr, SkipPast::Reference);
205*04eeddc0SDimitry Andric       if (PointeeLoc == nullptr)
206*04eeddc0SDimitry Andric         break;
207*04eeddc0SDimitry Andric 
208*04eeddc0SDimitry Andric       auto &PointerLoc = Env.createStorageLocation(*S);
209*04eeddc0SDimitry Andric       auto &PointerVal =
210*04eeddc0SDimitry Andric           Env.takeOwnership(std::make_unique<PointerValue>(*PointeeLoc));
211*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, PointerLoc);
212*04eeddc0SDimitry Andric       Env.setValue(PointerLoc, PointerVal);
213*04eeddc0SDimitry Andric       break;
214*04eeddc0SDimitry Andric     }
215*04eeddc0SDimitry Andric     default:
216*04eeddc0SDimitry Andric       // FIXME: Add support for UO_LNot.
217*04eeddc0SDimitry Andric       break;
218*04eeddc0SDimitry Andric     }
219*04eeddc0SDimitry Andric   }
220*04eeddc0SDimitry Andric 
221*04eeddc0SDimitry Andric   void VisitCXXThisExpr(const CXXThisExpr *S) {
222*04eeddc0SDimitry Andric     auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation();
223*04eeddc0SDimitry Andric     assert(ThisPointeeLoc != nullptr);
224*04eeddc0SDimitry Andric 
225*04eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
226*04eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
227*04eeddc0SDimitry Andric     Env.setValue(Loc, Env.takeOwnership(
228*04eeddc0SDimitry Andric                           std::make_unique<PointerValue>(*ThisPointeeLoc)));
229*04eeddc0SDimitry Andric   }
230*04eeddc0SDimitry Andric 
231*04eeddc0SDimitry Andric   void VisitMemberExpr(const MemberExpr *S) {
232*04eeddc0SDimitry Andric     ValueDecl *Member = S->getMemberDecl();
233*04eeddc0SDimitry Andric     assert(Member != nullptr);
234*04eeddc0SDimitry Andric 
235*04eeddc0SDimitry Andric     // FIXME: Consider assigning pointer values to function member expressions.
236*04eeddc0SDimitry Andric     if (Member->isFunctionOrFunctionTemplate())
237*04eeddc0SDimitry Andric       return;
238*04eeddc0SDimitry Andric 
239*04eeddc0SDimitry Andric     // The receiver can be either a value or a pointer to a value. Skip past the
240*04eeddc0SDimitry Andric     // indirection to handle both cases.
241*04eeddc0SDimitry Andric     auto *BaseLoc = cast_or_null<AggregateStorageLocation>(
242*04eeddc0SDimitry Andric         Env.getStorageLocation(*S->getBase(), SkipPast::ReferenceThenPointer));
243*04eeddc0SDimitry Andric     if (BaseLoc == nullptr)
244*04eeddc0SDimitry Andric       return;
245*04eeddc0SDimitry Andric 
246*04eeddc0SDimitry Andric     // FIXME: Add support for union types.
247*04eeddc0SDimitry Andric     if (BaseLoc->getType()->isUnionType())
248*04eeddc0SDimitry Andric       return;
249*04eeddc0SDimitry Andric 
250*04eeddc0SDimitry Andric     auto &MemberLoc = BaseLoc->getChild(*Member);
251*04eeddc0SDimitry Andric     if (MemberLoc.getType()->isReferenceType()) {
252*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, MemberLoc);
253*04eeddc0SDimitry Andric     } else {
254*04eeddc0SDimitry Andric       auto &Loc = Env.createStorageLocation(*S);
255*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, Loc);
256*04eeddc0SDimitry Andric       Env.setValue(
257*04eeddc0SDimitry Andric           Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(MemberLoc)));
258*04eeddc0SDimitry Andric     }
259*04eeddc0SDimitry Andric   }
260*04eeddc0SDimitry Andric 
261*04eeddc0SDimitry Andric   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
262*04eeddc0SDimitry Andric     const Expr *InitExpr = S->getExpr();
263*04eeddc0SDimitry Andric     assert(InitExpr != nullptr);
264*04eeddc0SDimitry Andric 
265*04eeddc0SDimitry Andric     Value *InitExprVal = Env.getValue(*InitExpr, SkipPast::None);
266*04eeddc0SDimitry Andric     if (InitExprVal == nullptr)
267*04eeddc0SDimitry Andric       return;
268*04eeddc0SDimitry Andric 
269*04eeddc0SDimitry Andric     const FieldDecl *Field = S->getField();
270*04eeddc0SDimitry Andric     assert(Field != nullptr);
271*04eeddc0SDimitry Andric 
272*04eeddc0SDimitry Andric     auto &ThisLoc =
273*04eeddc0SDimitry Andric         *cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
274*04eeddc0SDimitry Andric     auto &FieldLoc = ThisLoc.getChild(*Field);
275*04eeddc0SDimitry Andric     Env.setValue(FieldLoc, *InitExprVal);
276*04eeddc0SDimitry Andric   }
277*04eeddc0SDimitry Andric 
278*04eeddc0SDimitry Andric   void VisitCXXConstructExpr(const CXXConstructExpr *S) {
279*04eeddc0SDimitry Andric     const CXXConstructorDecl *ConstructorDecl = S->getConstructor();
280*04eeddc0SDimitry Andric     assert(ConstructorDecl != nullptr);
281*04eeddc0SDimitry Andric 
282*04eeddc0SDimitry Andric     if (ConstructorDecl->isCopyOrMoveConstructor()) {
283*04eeddc0SDimitry Andric       assert(S->getNumArgs() == 1);
284*04eeddc0SDimitry Andric 
285*04eeddc0SDimitry Andric       const Expr *Arg = S->getArg(0);
286*04eeddc0SDimitry Andric       assert(Arg != nullptr);
287*04eeddc0SDimitry Andric 
288*04eeddc0SDimitry Andric       if (S->isElidable()) {
289*04eeddc0SDimitry Andric         auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
290*04eeddc0SDimitry Andric         if (ArgLoc == nullptr)
291*04eeddc0SDimitry Andric           return;
292*04eeddc0SDimitry Andric 
293*04eeddc0SDimitry Andric         Env.setStorageLocation(*S, *ArgLoc);
294*04eeddc0SDimitry Andric       } else if (auto *ArgVal = Env.getValue(*Arg, SkipPast::Reference)) {
295*04eeddc0SDimitry Andric         auto &Loc = Env.createStorageLocation(*S);
296*04eeddc0SDimitry Andric         Env.setStorageLocation(*S, Loc);
297*04eeddc0SDimitry Andric         Env.setValue(Loc, *ArgVal);
298*04eeddc0SDimitry Andric       }
299*04eeddc0SDimitry Andric       return;
300*04eeddc0SDimitry Andric     }
301*04eeddc0SDimitry Andric 
302*04eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
303*04eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
304*04eeddc0SDimitry Andric     if (Value *Val = Env.createValue(S->getType()))
305*04eeddc0SDimitry Andric       Env.setValue(Loc, *Val);
306*04eeddc0SDimitry Andric   }
307*04eeddc0SDimitry Andric 
308*04eeddc0SDimitry Andric   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
309*04eeddc0SDimitry Andric     if (S->getOperator() == OO_Equal) {
310*04eeddc0SDimitry Andric       assert(S->getNumArgs() == 2);
311*04eeddc0SDimitry Andric 
312*04eeddc0SDimitry Andric       const Expr *Arg0 = S->getArg(0);
313*04eeddc0SDimitry Andric       assert(Arg0 != nullptr);
314*04eeddc0SDimitry Andric 
315*04eeddc0SDimitry Andric       const Expr *Arg1 = S->getArg(1);
316*04eeddc0SDimitry Andric       assert(Arg1 != nullptr);
317*04eeddc0SDimitry Andric 
318*04eeddc0SDimitry Andric       // Evaluate only copy and move assignment operators.
319*04eeddc0SDimitry Andric       auto *Arg0Type = Arg0->getType()->getUnqualifiedDesugaredType();
320*04eeddc0SDimitry Andric       auto *Arg1Type = Arg1->getType()->getUnqualifiedDesugaredType();
321*04eeddc0SDimitry Andric       if (Arg0Type != Arg1Type)
322*04eeddc0SDimitry Andric         return;
323*04eeddc0SDimitry Andric 
324*04eeddc0SDimitry Andric       auto *ObjectLoc = Env.getStorageLocation(*Arg0, SkipPast::Reference);
325*04eeddc0SDimitry Andric       if (ObjectLoc == nullptr)
326*04eeddc0SDimitry Andric         return;
327*04eeddc0SDimitry Andric 
328*04eeddc0SDimitry Andric       auto *Val = Env.getValue(*Arg1, SkipPast::Reference);
329*04eeddc0SDimitry Andric       if (Val == nullptr)
330*04eeddc0SDimitry Andric         return;
331*04eeddc0SDimitry Andric 
332*04eeddc0SDimitry Andric       Env.setValue(*ObjectLoc, *Val);
333*04eeddc0SDimitry Andric     }
334*04eeddc0SDimitry Andric   }
335*04eeddc0SDimitry Andric 
336*04eeddc0SDimitry Andric   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
337*04eeddc0SDimitry Andric     if (S->getCastKind() == CK_ConstructorConversion) {
338*04eeddc0SDimitry Andric       // The CFG does not contain `ParenExpr` as top-level statements in basic
339*04eeddc0SDimitry Andric       // blocks, however sub-expressions can still be of that type.
340*04eeddc0SDimitry Andric       assert(S->getSubExpr() != nullptr);
341*04eeddc0SDimitry Andric       const Expr *SubExpr = S->getSubExpr();
342*04eeddc0SDimitry Andric       assert(SubExpr != nullptr);
343*04eeddc0SDimitry Andric 
344*04eeddc0SDimitry Andric       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
345*04eeddc0SDimitry Andric       if (SubExprLoc == nullptr)
346*04eeddc0SDimitry Andric         return;
347*04eeddc0SDimitry Andric 
348*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, *SubExprLoc);
349*04eeddc0SDimitry Andric     }
350*04eeddc0SDimitry Andric   }
351*04eeddc0SDimitry Andric 
352*04eeddc0SDimitry Andric   void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
353*04eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
354*04eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
355*04eeddc0SDimitry Andric     if (Value *Val = Env.createValue(S->getType()))
356*04eeddc0SDimitry Andric       Env.setValue(Loc, *Val);
357*04eeddc0SDimitry Andric   }
358*04eeddc0SDimitry Andric 
359*04eeddc0SDimitry Andric   void VisitCallExpr(const CallExpr *S) {
360*04eeddc0SDimitry Andric     if (S->isCallToStdMove()) {
361*04eeddc0SDimitry Andric       assert(S->getNumArgs() == 1);
362*04eeddc0SDimitry Andric 
363*04eeddc0SDimitry Andric       const Expr *Arg = S->getArg(0);
364*04eeddc0SDimitry Andric       assert(Arg != nullptr);
365*04eeddc0SDimitry Andric 
366*04eeddc0SDimitry Andric       auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::None);
367*04eeddc0SDimitry Andric       if (ArgLoc == nullptr)
368*04eeddc0SDimitry Andric         return;
369*04eeddc0SDimitry Andric 
370*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, *ArgLoc);
371*04eeddc0SDimitry Andric     }
372*04eeddc0SDimitry Andric   }
373*04eeddc0SDimitry Andric 
374*04eeddc0SDimitry Andric   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
375*04eeddc0SDimitry Andric     const Expr *SubExpr = S->getSubExpr();
376*04eeddc0SDimitry Andric     assert(SubExpr != nullptr);
377*04eeddc0SDimitry Andric 
378*04eeddc0SDimitry Andric     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
379*04eeddc0SDimitry Andric     if (SubExprLoc == nullptr)
380*04eeddc0SDimitry Andric       return;
381*04eeddc0SDimitry Andric 
382*04eeddc0SDimitry Andric     Env.setStorageLocation(*S, *SubExprLoc);
383*04eeddc0SDimitry Andric   }
384*04eeddc0SDimitry Andric 
385*04eeddc0SDimitry Andric   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
386*04eeddc0SDimitry Andric     const Expr *SubExpr = S->getSubExpr();
387*04eeddc0SDimitry Andric     assert(SubExpr != nullptr);
388*04eeddc0SDimitry Andric 
389*04eeddc0SDimitry Andric     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
390*04eeddc0SDimitry Andric     if (SubExprLoc == nullptr)
391*04eeddc0SDimitry Andric       return;
392*04eeddc0SDimitry Andric 
393*04eeddc0SDimitry Andric     Env.setStorageLocation(*S, *SubExprLoc);
394*04eeddc0SDimitry Andric   }
395*04eeddc0SDimitry Andric 
396*04eeddc0SDimitry Andric   void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
397*04eeddc0SDimitry Andric     if (S->getCastKind() == CK_NoOp) {
398*04eeddc0SDimitry Andric       const Expr *SubExpr = S->getSubExpr();
399*04eeddc0SDimitry Andric       assert(SubExpr != nullptr);
400*04eeddc0SDimitry Andric 
401*04eeddc0SDimitry Andric       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
402*04eeddc0SDimitry Andric       if (SubExprLoc == nullptr)
403*04eeddc0SDimitry Andric         return;
404*04eeddc0SDimitry Andric 
405*04eeddc0SDimitry Andric       Env.setStorageLocation(*S, *SubExprLoc);
406*04eeddc0SDimitry Andric     }
407*04eeddc0SDimitry Andric   }
408*04eeddc0SDimitry Andric 
409*04eeddc0SDimitry Andric   void VisitConditionalOperator(const ConditionalOperator *S) {
410*04eeddc0SDimitry Andric     // FIXME: Revisit this once flow conditions are added to the framework. For
411*04eeddc0SDimitry Andric     // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
412*04eeddc0SDimitry Andric     // condition.
413*04eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
414*04eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
415*04eeddc0SDimitry Andric     if (Value *Val = Env.createValue(S->getType()))
416*04eeddc0SDimitry Andric       Env.setValue(Loc, *Val);
417*04eeddc0SDimitry Andric   }
418*04eeddc0SDimitry Andric 
419*04eeddc0SDimitry Andric   void VisitInitListExpr(const InitListExpr *S) {
420*04eeddc0SDimitry Andric     QualType Type = S->getType();
421*04eeddc0SDimitry Andric 
422*04eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
423*04eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
424*04eeddc0SDimitry Andric 
425*04eeddc0SDimitry Andric     auto *Val = Env.createValue(Type);
426*04eeddc0SDimitry Andric     if (Val == nullptr)
427*04eeddc0SDimitry Andric       return;
428*04eeddc0SDimitry Andric 
429*04eeddc0SDimitry Andric     Env.setValue(Loc, *Val);
430*04eeddc0SDimitry Andric 
431*04eeddc0SDimitry Andric     if (Type->isStructureOrClassType()) {
432*04eeddc0SDimitry Andric       for (auto IT : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) {
433*04eeddc0SDimitry Andric         const FieldDecl *Field = std::get<0>(IT);
434*04eeddc0SDimitry Andric         assert(Field != nullptr);
435*04eeddc0SDimitry Andric 
436*04eeddc0SDimitry Andric         const Expr *Init = std::get<1>(IT);
437*04eeddc0SDimitry Andric         assert(Init != nullptr);
438*04eeddc0SDimitry Andric 
439*04eeddc0SDimitry Andric         if (Value *InitVal = Env.getValue(*Init, SkipPast::None))
440*04eeddc0SDimitry Andric           cast<StructValue>(Val)->setChild(*Field, *InitVal);
441*04eeddc0SDimitry Andric       }
442*04eeddc0SDimitry Andric     }
443*04eeddc0SDimitry Andric     // FIXME: Implement array initialization.
444*04eeddc0SDimitry Andric   }
445*04eeddc0SDimitry Andric 
446*04eeddc0SDimitry Andric   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
447*04eeddc0SDimitry Andric     auto &Loc = Env.createStorageLocation(*S);
448*04eeddc0SDimitry Andric     Env.setStorageLocation(*S, Loc);
449*04eeddc0SDimitry Andric     Env.setValue(Loc, Env.getBoolLiteralValue(S->getValue()));
450*04eeddc0SDimitry Andric   }
451*04eeddc0SDimitry Andric 
452*04eeddc0SDimitry Andric private:
453*04eeddc0SDimitry Andric   Environment &Env;
454*04eeddc0SDimitry Andric };
455*04eeddc0SDimitry Andric 
456*04eeddc0SDimitry Andric void transfer(const Stmt &S, Environment &Env) {
457*04eeddc0SDimitry Andric   assert(!isa<ParenExpr>(&S));
458*04eeddc0SDimitry Andric   TransferVisitor(Env).Visit(&S);
459*04eeddc0SDimitry Andric }
460*04eeddc0SDimitry Andric 
461*04eeddc0SDimitry Andric } // namespace dataflow
462*04eeddc0SDimitry Andric } // namespace clang
463