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