104eeddc0SDimitry Andric //===-- Transfer.cpp --------------------------------------------*- C++ -*-===// 204eeddc0SDimitry Andric // 304eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 404eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 504eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 604eeddc0SDimitry Andric // 704eeddc0SDimitry Andric //===----------------------------------------------------------------------===// 804eeddc0SDimitry Andric // 904eeddc0SDimitry Andric // This file defines transfer functions that evaluate program statements and 1004eeddc0SDimitry Andric // update an environment accordingly. 1104eeddc0SDimitry Andric // 1204eeddc0SDimitry Andric //===----------------------------------------------------------------------===// 1304eeddc0SDimitry Andric 1404eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/Transfer.h" 1504eeddc0SDimitry Andric #include "clang/AST/Decl.h" 1604eeddc0SDimitry Andric #include "clang/AST/DeclBase.h" 1704eeddc0SDimitry Andric #include "clang/AST/DeclCXX.h" 1804eeddc0SDimitry Andric #include "clang/AST/Expr.h" 1904eeddc0SDimitry Andric #include "clang/AST/ExprCXX.h" 2004eeddc0SDimitry Andric #include "clang/AST/OperationKinds.h" 2104eeddc0SDimitry Andric #include "clang/AST/Stmt.h" 2204eeddc0SDimitry Andric #include "clang/AST/StmtVisitor.h" 23*972a253aSDimitry Andric #include "clang/Analysis/FlowSensitive/ControlFlowContext.h" 2404eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" 25*972a253aSDimitry Andric #include "clang/Analysis/FlowSensitive/NoopAnalysis.h" 2681ad6265SDimitry Andric #include "clang/Analysis/FlowSensitive/Value.h" 2781ad6265SDimitry Andric #include "clang/Basic/Builtins.h" 2804eeddc0SDimitry Andric #include "clang/Basic/OperatorKinds.h" 2904eeddc0SDimitry Andric #include "llvm/ADT/STLExtras.h" 3004eeddc0SDimitry Andric #include "llvm/Support/Casting.h" 3104eeddc0SDimitry Andric #include <cassert> 3204eeddc0SDimitry Andric #include <memory> 3304eeddc0SDimitry Andric #include <tuple> 3404eeddc0SDimitry Andric 3504eeddc0SDimitry Andric namespace clang { 3604eeddc0SDimitry Andric namespace dataflow { 3704eeddc0SDimitry Andric 3881ad6265SDimitry Andric static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS, 3981ad6265SDimitry Andric Environment &Env) { 4081ad6265SDimitry Andric if (auto *LHSValue = 4181ad6265SDimitry Andric dyn_cast_or_null<BoolValue>(Env.getValue(LHS, SkipPast::Reference))) 4281ad6265SDimitry Andric if (auto *RHSValue = 4381ad6265SDimitry Andric dyn_cast_or_null<BoolValue>(Env.getValue(RHS, SkipPast::Reference))) 4481ad6265SDimitry Andric return Env.makeIff(*LHSValue, *RHSValue); 4581ad6265SDimitry Andric 4681ad6265SDimitry Andric return Env.makeAtomicBoolValue(); 4704eeddc0SDimitry Andric } 4804eeddc0SDimitry Andric 4904eeddc0SDimitry Andric class TransferVisitor : public ConstStmtVisitor<TransferVisitor> { 5004eeddc0SDimitry Andric public: 51*972a253aSDimitry Andric TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env, 52*972a253aSDimitry Andric TransferOptions Options) 53*972a253aSDimitry Andric : StmtToEnv(StmtToEnv), Env(Env), Options(Options) {} 5404eeddc0SDimitry Andric 5504eeddc0SDimitry Andric void VisitBinaryOperator(const BinaryOperator *S) { 5681ad6265SDimitry Andric const Expr *LHS = S->getLHS(); 5704eeddc0SDimitry Andric assert(LHS != nullptr); 5881ad6265SDimitry Andric 5981ad6265SDimitry Andric const Expr *RHS = S->getRHS(); 6081ad6265SDimitry Andric assert(RHS != nullptr); 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric switch (S->getOpcode()) { 6381ad6265SDimitry Andric case BO_Assign: { 6404eeddc0SDimitry Andric auto *LHSLoc = Env.getStorageLocation(*LHS, SkipPast::Reference); 6504eeddc0SDimitry Andric if (LHSLoc == nullptr) 6681ad6265SDimitry Andric break; 6704eeddc0SDimitry Andric 6881ad6265SDimitry Andric auto *RHSVal = Env.getValue(*RHS, SkipPast::Reference); 6904eeddc0SDimitry Andric if (RHSVal == nullptr) 7081ad6265SDimitry Andric break; 7104eeddc0SDimitry Andric 7204eeddc0SDimitry Andric // Assign a value to the storage location of the left-hand side. 7304eeddc0SDimitry Andric Env.setValue(*LHSLoc, *RHSVal); 7404eeddc0SDimitry Andric 7504eeddc0SDimitry Andric // Assign a storage location for the whole expression. 7604eeddc0SDimitry Andric Env.setStorageLocation(*S, *LHSLoc); 7781ad6265SDimitry Andric break; 7804eeddc0SDimitry Andric } 7981ad6265SDimitry Andric case BO_LAnd: 8081ad6265SDimitry Andric case BO_LOr: { 8181ad6265SDimitry Andric BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS); 8281ad6265SDimitry Andric BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS); 8381ad6265SDimitry Andric 8481ad6265SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 8581ad6265SDimitry Andric Env.setStorageLocation(*S, Loc); 8681ad6265SDimitry Andric if (S->getOpcode() == BO_LAnd) 8781ad6265SDimitry Andric Env.setValue(Loc, Env.makeAnd(LHSVal, RHSVal)); 8881ad6265SDimitry Andric else 8981ad6265SDimitry Andric Env.setValue(Loc, Env.makeOr(LHSVal, RHSVal)); 9081ad6265SDimitry Andric break; 9181ad6265SDimitry Andric } 9281ad6265SDimitry Andric case BO_NE: 9381ad6265SDimitry Andric case BO_EQ: { 9481ad6265SDimitry Andric auto &LHSEqRHSValue = evaluateBooleanEquality(*LHS, *RHS, Env); 9581ad6265SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 9681ad6265SDimitry Andric Env.setStorageLocation(*S, Loc); 9781ad6265SDimitry Andric Env.setValue(Loc, S->getOpcode() == BO_EQ ? LHSEqRHSValue 9881ad6265SDimitry Andric : Env.makeNot(LHSEqRHSValue)); 9981ad6265SDimitry Andric break; 10081ad6265SDimitry Andric } 10181ad6265SDimitry Andric case BO_Comma: { 10281ad6265SDimitry Andric if (auto *Loc = Env.getStorageLocation(*RHS, SkipPast::None)) 10381ad6265SDimitry Andric Env.setStorageLocation(*S, *Loc); 10481ad6265SDimitry Andric break; 10581ad6265SDimitry Andric } 10681ad6265SDimitry Andric default: 10781ad6265SDimitry Andric break; 10881ad6265SDimitry Andric } 10904eeddc0SDimitry Andric } 11004eeddc0SDimitry Andric 11104eeddc0SDimitry Andric void VisitDeclRefExpr(const DeclRefExpr *S) { 11204eeddc0SDimitry Andric assert(S->getDecl() != nullptr); 11304eeddc0SDimitry Andric auto *DeclLoc = Env.getStorageLocation(*S->getDecl(), SkipPast::None); 11404eeddc0SDimitry Andric if (DeclLoc == nullptr) 11504eeddc0SDimitry Andric return; 11604eeddc0SDimitry Andric 11704eeddc0SDimitry Andric if (S->getDecl()->getType()->isReferenceType()) { 11804eeddc0SDimitry Andric Env.setStorageLocation(*S, *DeclLoc); 11904eeddc0SDimitry Andric } else { 12004eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 12104eeddc0SDimitry Andric auto &Val = Env.takeOwnership(std::make_unique<ReferenceValue>(*DeclLoc)); 12204eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 12304eeddc0SDimitry Andric Env.setValue(Loc, Val); 12404eeddc0SDimitry Andric } 12504eeddc0SDimitry Andric } 12604eeddc0SDimitry Andric 12704eeddc0SDimitry Andric void VisitDeclStmt(const DeclStmt *S) { 12804eeddc0SDimitry Andric // Group decls are converted into single decls in the CFG so the cast below 12904eeddc0SDimitry Andric // is safe. 13004eeddc0SDimitry Andric const auto &D = *cast<VarDecl>(S->getSingleDecl()); 13181ad6265SDimitry Andric 13281ad6265SDimitry Andric // Static local vars are already initialized in `Environment`. 13381ad6265SDimitry Andric if (D.hasGlobalStorage()) 13481ad6265SDimitry Andric return; 13581ad6265SDimitry Andric 13604eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(D); 13704eeddc0SDimitry Andric Env.setStorageLocation(D, Loc); 13804eeddc0SDimitry Andric 13904eeddc0SDimitry Andric const Expr *InitExpr = D.getInit(); 14004eeddc0SDimitry Andric if (InitExpr == nullptr) { 14104eeddc0SDimitry Andric // No initializer expression - associate `Loc` with a new value. 14204eeddc0SDimitry Andric if (Value *Val = Env.createValue(D.getType())) 14304eeddc0SDimitry Andric Env.setValue(Loc, *Val); 14404eeddc0SDimitry Andric return; 14504eeddc0SDimitry Andric } 14604eeddc0SDimitry Andric 14704eeddc0SDimitry Andric if (D.getType()->isReferenceType()) { 14804eeddc0SDimitry Andric // Initializing a reference variable - do not create a reference to 14904eeddc0SDimitry Andric // reference. 15004eeddc0SDimitry Andric if (auto *InitExprLoc = 15104eeddc0SDimitry Andric Env.getStorageLocation(*InitExpr, SkipPast::Reference)) { 15204eeddc0SDimitry Andric auto &Val = 15304eeddc0SDimitry Andric Env.takeOwnership(std::make_unique<ReferenceValue>(*InitExprLoc)); 15404eeddc0SDimitry Andric Env.setValue(Loc, Val); 15504eeddc0SDimitry Andric } 15681ad6265SDimitry Andric } else if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) { 15781ad6265SDimitry Andric Env.setValue(Loc, *InitExprVal); 15804eeddc0SDimitry Andric } 15904eeddc0SDimitry Andric 16081ad6265SDimitry Andric if (Env.getValue(Loc) == nullptr) { 16181ad6265SDimitry Andric // We arrive here in (the few) cases where an expression is intentionally 16281ad6265SDimitry Andric // "uninterpreted". There are two ways to handle this situation: propagate 16381ad6265SDimitry Andric // the status, so that uninterpreted initializers result in uninterpreted 16481ad6265SDimitry Andric // variables, or provide a default value. We choose the latter so that 16581ad6265SDimitry Andric // later refinements of the variable can be used for reasoning about the 16681ad6265SDimitry Andric // surrounding code. 16781ad6265SDimitry Andric // 16881ad6265SDimitry Andric // FIXME. If and when we interpret all language cases, change this to 16981ad6265SDimitry Andric // assert that `InitExpr` is interpreted, rather than supplying a default 17081ad6265SDimitry Andric // value (assuming we don't update the environment API to return 17181ad6265SDimitry Andric // references). 17204eeddc0SDimitry Andric if (Value *Val = Env.createValue(D.getType())) 17304eeddc0SDimitry Andric Env.setValue(Loc, *Val); 17481ad6265SDimitry Andric } 17581ad6265SDimitry Andric 17681ad6265SDimitry Andric if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D)) { 17781ad6265SDimitry Andric // If VarDecl is a DecompositionDecl, evaluate each of its bindings. This 17881ad6265SDimitry Andric // needs to be evaluated after initializing the values in the storage for 17981ad6265SDimitry Andric // VarDecl, as the bindings refer to them. 18081ad6265SDimitry Andric // FIXME: Add support for ArraySubscriptExpr. 18181ad6265SDimitry Andric // FIXME: Consider adding AST nodes that are used for structured bindings 18281ad6265SDimitry Andric // to the CFG. 18381ad6265SDimitry Andric for (const auto *B : Decomp->bindings()) { 18481ad6265SDimitry Andric auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding()); 18581ad6265SDimitry Andric if (ME == nullptr) 18681ad6265SDimitry Andric continue; 18781ad6265SDimitry Andric 18881ad6265SDimitry Andric auto *DE = dyn_cast_or_null<DeclRefExpr>(ME->getBase()); 18981ad6265SDimitry Andric if (DE == nullptr) 19081ad6265SDimitry Andric continue; 19181ad6265SDimitry Andric 19281ad6265SDimitry Andric // ME and its base haven't been visited because they aren't included in 19381ad6265SDimitry Andric // the statements of the CFG basic block. 19481ad6265SDimitry Andric VisitDeclRefExpr(DE); 19581ad6265SDimitry Andric VisitMemberExpr(ME); 19681ad6265SDimitry Andric 19781ad6265SDimitry Andric if (auto *Loc = Env.getStorageLocation(*ME, SkipPast::Reference)) 19881ad6265SDimitry Andric Env.setStorageLocation(*B, *Loc); 19981ad6265SDimitry Andric } 20004eeddc0SDimitry Andric } 20104eeddc0SDimitry Andric } 20204eeddc0SDimitry Andric 20304eeddc0SDimitry Andric void VisitImplicitCastExpr(const ImplicitCastExpr *S) { 20481ad6265SDimitry Andric const Expr *SubExpr = S->getSubExpr(); 20504eeddc0SDimitry Andric assert(SubExpr != nullptr); 20604eeddc0SDimitry Andric 20704eeddc0SDimitry Andric switch (S->getCastKind()) { 20881ad6265SDimitry Andric case CK_IntegralToBoolean: { 20981ad6265SDimitry Andric // This cast creates a new, boolean value from the integral value. We 21081ad6265SDimitry Andric // model that with a fresh value in the environment, unless it's already a 21181ad6265SDimitry Andric // boolean. 21281ad6265SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 21381ad6265SDimitry Andric Env.setStorageLocation(*S, Loc); 21481ad6265SDimitry Andric if (auto *SubExprVal = dyn_cast_or_null<BoolValue>( 21581ad6265SDimitry Andric Env.getValue(*SubExpr, SkipPast::Reference))) 21681ad6265SDimitry Andric Env.setValue(Loc, *SubExprVal); 21781ad6265SDimitry Andric else 21881ad6265SDimitry Andric // FIXME: If integer modeling is added, then update this code to create 21981ad6265SDimitry Andric // the boolean based on the integer model. 22081ad6265SDimitry Andric Env.setValue(Loc, Env.makeAtomicBoolValue()); 22181ad6265SDimitry Andric break; 22281ad6265SDimitry Andric } 22381ad6265SDimitry Andric 22404eeddc0SDimitry Andric case CK_LValueToRValue: { 22504eeddc0SDimitry Andric auto *SubExprVal = Env.getValue(*SubExpr, SkipPast::Reference); 22604eeddc0SDimitry Andric if (SubExprVal == nullptr) 22704eeddc0SDimitry Andric break; 22804eeddc0SDimitry Andric 22904eeddc0SDimitry Andric auto &ExprLoc = Env.createStorageLocation(*S); 23004eeddc0SDimitry Andric Env.setStorageLocation(*S, ExprLoc); 23104eeddc0SDimitry Andric Env.setValue(ExprLoc, *SubExprVal); 23204eeddc0SDimitry Andric break; 23304eeddc0SDimitry Andric } 23481ad6265SDimitry Andric 23581ad6265SDimitry Andric case CK_IntegralCast: 23681ad6265SDimitry Andric // FIXME: This cast creates a new integral value from the 23781ad6265SDimitry Andric // subexpression. But, because we don't model integers, we don't 23881ad6265SDimitry Andric // distinguish between this new value and the underlying one. If integer 23981ad6265SDimitry Andric // modeling is added, then update this code to create a fresh location and 24081ad6265SDimitry Andric // value. 24181ad6265SDimitry Andric case CK_UncheckedDerivedToBase: 24281ad6265SDimitry Andric case CK_ConstructorConversion: 24381ad6265SDimitry Andric case CK_UserDefinedConversion: 24481ad6265SDimitry Andric // FIXME: Add tests that excercise CK_UncheckedDerivedToBase, 24581ad6265SDimitry Andric // CK_ConstructorConversion, and CK_UserDefinedConversion. 24604eeddc0SDimitry Andric case CK_NoOp: { 24704eeddc0SDimitry Andric // FIXME: Consider making `Environment::getStorageLocation` skip noop 24804eeddc0SDimitry Andric // expressions (this and other similar expressions in the file) instead of 24904eeddc0SDimitry Andric // assigning them storage locations. 25004eeddc0SDimitry Andric auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None); 25104eeddc0SDimitry Andric if (SubExprLoc == nullptr) 25204eeddc0SDimitry Andric break; 25304eeddc0SDimitry Andric 25404eeddc0SDimitry Andric Env.setStorageLocation(*S, *SubExprLoc); 25504eeddc0SDimitry Andric break; 25604eeddc0SDimitry Andric } 25781ad6265SDimitry Andric case CK_NullToPointer: 25881ad6265SDimitry Andric case CK_NullToMemberPointer: { 25981ad6265SDimitry Andric auto &Loc = Env.createStorageLocation(S->getType()); 26081ad6265SDimitry Andric Env.setStorageLocation(*S, Loc); 26181ad6265SDimitry Andric 26281ad6265SDimitry Andric auto &NullPointerVal = 26381ad6265SDimitry Andric Env.getOrCreateNullPointerValue(S->getType()->getPointeeType()); 26481ad6265SDimitry Andric Env.setValue(Loc, NullPointerVal); 26581ad6265SDimitry Andric break; 26681ad6265SDimitry Andric } 26704eeddc0SDimitry Andric default: 26804eeddc0SDimitry Andric break; 26904eeddc0SDimitry Andric } 27004eeddc0SDimitry Andric } 27104eeddc0SDimitry Andric 27204eeddc0SDimitry Andric void VisitUnaryOperator(const UnaryOperator *S) { 27381ad6265SDimitry Andric const Expr *SubExpr = S->getSubExpr(); 27404eeddc0SDimitry Andric assert(SubExpr != nullptr); 27504eeddc0SDimitry Andric 27604eeddc0SDimitry Andric switch (S->getOpcode()) { 27704eeddc0SDimitry Andric case UO_Deref: { 27804eeddc0SDimitry Andric // Skip past a reference to handle dereference of a dependent pointer. 27904eeddc0SDimitry Andric const auto *SubExprVal = cast_or_null<PointerValue>( 28004eeddc0SDimitry Andric Env.getValue(*SubExpr, SkipPast::Reference)); 28104eeddc0SDimitry Andric if (SubExprVal == nullptr) 28204eeddc0SDimitry Andric break; 28304eeddc0SDimitry Andric 28404eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 28504eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 28604eeddc0SDimitry Andric Env.setValue(Loc, Env.takeOwnership(std::make_unique<ReferenceValue>( 28704eeddc0SDimitry Andric SubExprVal->getPointeeLoc()))); 28804eeddc0SDimitry Andric break; 28904eeddc0SDimitry Andric } 29004eeddc0SDimitry Andric case UO_AddrOf: { 29104eeddc0SDimitry Andric // Do not form a pointer to a reference. If `SubExpr` is assigned a 29204eeddc0SDimitry Andric // `ReferenceValue` then form a value that points to the location of its 29304eeddc0SDimitry Andric // pointee. 29404eeddc0SDimitry Andric StorageLocation *PointeeLoc = 29504eeddc0SDimitry Andric Env.getStorageLocation(*SubExpr, SkipPast::Reference); 29604eeddc0SDimitry Andric if (PointeeLoc == nullptr) 29704eeddc0SDimitry Andric break; 29804eeddc0SDimitry Andric 29904eeddc0SDimitry Andric auto &PointerLoc = Env.createStorageLocation(*S); 30004eeddc0SDimitry Andric auto &PointerVal = 30104eeddc0SDimitry Andric Env.takeOwnership(std::make_unique<PointerValue>(*PointeeLoc)); 30204eeddc0SDimitry Andric Env.setStorageLocation(*S, PointerLoc); 30304eeddc0SDimitry Andric Env.setValue(PointerLoc, PointerVal); 30404eeddc0SDimitry Andric break; 30504eeddc0SDimitry Andric } 30681ad6265SDimitry Andric case UO_LNot: { 30781ad6265SDimitry Andric auto *SubExprVal = 30881ad6265SDimitry Andric dyn_cast_or_null<BoolValue>(Env.getValue(*SubExpr, SkipPast::None)); 30981ad6265SDimitry Andric if (SubExprVal == nullptr) 31081ad6265SDimitry Andric break; 31181ad6265SDimitry Andric 31281ad6265SDimitry Andric auto &ExprLoc = Env.createStorageLocation(*S); 31381ad6265SDimitry Andric Env.setStorageLocation(*S, ExprLoc); 31481ad6265SDimitry Andric Env.setValue(ExprLoc, Env.makeNot(*SubExprVal)); 31581ad6265SDimitry Andric break; 31681ad6265SDimitry Andric } 31704eeddc0SDimitry Andric default: 31804eeddc0SDimitry Andric break; 31904eeddc0SDimitry Andric } 32004eeddc0SDimitry Andric } 32104eeddc0SDimitry Andric 32204eeddc0SDimitry Andric void VisitCXXThisExpr(const CXXThisExpr *S) { 32304eeddc0SDimitry Andric auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation(); 32481ad6265SDimitry Andric if (ThisPointeeLoc == nullptr) 32581ad6265SDimitry Andric // Unions are not supported yet, and will not have a location for the 32681ad6265SDimitry Andric // `this` expression's pointee. 32781ad6265SDimitry Andric return; 32804eeddc0SDimitry Andric 32904eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 33004eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 33104eeddc0SDimitry Andric Env.setValue(Loc, Env.takeOwnership( 33204eeddc0SDimitry Andric std::make_unique<PointerValue>(*ThisPointeeLoc))); 33304eeddc0SDimitry Andric } 33404eeddc0SDimitry Andric 33504eeddc0SDimitry Andric void VisitMemberExpr(const MemberExpr *S) { 33604eeddc0SDimitry Andric ValueDecl *Member = S->getMemberDecl(); 33704eeddc0SDimitry Andric assert(Member != nullptr); 33804eeddc0SDimitry Andric 33904eeddc0SDimitry Andric // FIXME: Consider assigning pointer values to function member expressions. 34004eeddc0SDimitry Andric if (Member->isFunctionOrFunctionTemplate()) 34104eeddc0SDimitry Andric return; 34204eeddc0SDimitry Andric 34381ad6265SDimitry Andric if (auto *D = dyn_cast<VarDecl>(Member)) { 34481ad6265SDimitry Andric if (D->hasGlobalStorage()) { 34581ad6265SDimitry Andric auto *VarDeclLoc = Env.getStorageLocation(*D, SkipPast::None); 34681ad6265SDimitry Andric if (VarDeclLoc == nullptr) 34781ad6265SDimitry Andric return; 34881ad6265SDimitry Andric 34981ad6265SDimitry Andric if (VarDeclLoc->getType()->isReferenceType()) { 35081ad6265SDimitry Andric Env.setStorageLocation(*S, *VarDeclLoc); 35181ad6265SDimitry Andric } else { 35281ad6265SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 35381ad6265SDimitry Andric Env.setStorageLocation(*S, Loc); 35481ad6265SDimitry Andric Env.setValue(Loc, Env.takeOwnership( 35581ad6265SDimitry Andric std::make_unique<ReferenceValue>(*VarDeclLoc))); 35681ad6265SDimitry Andric } 35781ad6265SDimitry Andric return; 35881ad6265SDimitry Andric } 35981ad6265SDimitry Andric } 36081ad6265SDimitry Andric 36104eeddc0SDimitry Andric // The receiver can be either a value or a pointer to a value. Skip past the 36204eeddc0SDimitry Andric // indirection to handle both cases. 36304eeddc0SDimitry Andric auto *BaseLoc = cast_or_null<AggregateStorageLocation>( 36404eeddc0SDimitry Andric Env.getStorageLocation(*S->getBase(), SkipPast::ReferenceThenPointer)); 36504eeddc0SDimitry Andric if (BaseLoc == nullptr) 36604eeddc0SDimitry Andric return; 36704eeddc0SDimitry Andric 36804eeddc0SDimitry Andric // FIXME: Add support for union types. 36904eeddc0SDimitry Andric if (BaseLoc->getType()->isUnionType()) 37004eeddc0SDimitry Andric return; 37104eeddc0SDimitry Andric 37204eeddc0SDimitry Andric auto &MemberLoc = BaseLoc->getChild(*Member); 37304eeddc0SDimitry Andric if (MemberLoc.getType()->isReferenceType()) { 37404eeddc0SDimitry Andric Env.setStorageLocation(*S, MemberLoc); 37504eeddc0SDimitry Andric } else { 37604eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 37704eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 37804eeddc0SDimitry Andric Env.setValue( 37904eeddc0SDimitry Andric Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(MemberLoc))); 38004eeddc0SDimitry Andric } 38104eeddc0SDimitry Andric } 38204eeddc0SDimitry Andric 38304eeddc0SDimitry Andric void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) { 38404eeddc0SDimitry Andric const Expr *InitExpr = S->getExpr(); 38504eeddc0SDimitry Andric assert(InitExpr != nullptr); 38604eeddc0SDimitry Andric 38704eeddc0SDimitry Andric Value *InitExprVal = Env.getValue(*InitExpr, SkipPast::None); 38804eeddc0SDimitry Andric if (InitExprVal == nullptr) 38904eeddc0SDimitry Andric return; 39004eeddc0SDimitry Andric 39104eeddc0SDimitry Andric const FieldDecl *Field = S->getField(); 39204eeddc0SDimitry Andric assert(Field != nullptr); 39304eeddc0SDimitry Andric 39404eeddc0SDimitry Andric auto &ThisLoc = 39504eeddc0SDimitry Andric *cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 39604eeddc0SDimitry Andric auto &FieldLoc = ThisLoc.getChild(*Field); 39704eeddc0SDimitry Andric Env.setValue(FieldLoc, *InitExprVal); 39804eeddc0SDimitry Andric } 39904eeddc0SDimitry Andric 40004eeddc0SDimitry Andric void VisitCXXConstructExpr(const CXXConstructExpr *S) { 40104eeddc0SDimitry Andric const CXXConstructorDecl *ConstructorDecl = S->getConstructor(); 40204eeddc0SDimitry Andric assert(ConstructorDecl != nullptr); 40304eeddc0SDimitry Andric 40404eeddc0SDimitry Andric if (ConstructorDecl->isCopyOrMoveConstructor()) { 40504eeddc0SDimitry Andric assert(S->getNumArgs() == 1); 40604eeddc0SDimitry Andric 40704eeddc0SDimitry Andric const Expr *Arg = S->getArg(0); 40804eeddc0SDimitry Andric assert(Arg != nullptr); 40904eeddc0SDimitry Andric 41004eeddc0SDimitry Andric if (S->isElidable()) { 41104eeddc0SDimitry Andric auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference); 41204eeddc0SDimitry Andric if (ArgLoc == nullptr) 41304eeddc0SDimitry Andric return; 41404eeddc0SDimitry Andric 41504eeddc0SDimitry Andric Env.setStorageLocation(*S, *ArgLoc); 41604eeddc0SDimitry Andric } else if (auto *ArgVal = Env.getValue(*Arg, SkipPast::Reference)) { 41704eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 41804eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 41904eeddc0SDimitry Andric Env.setValue(Loc, *ArgVal); 42004eeddc0SDimitry Andric } 42104eeddc0SDimitry Andric return; 42204eeddc0SDimitry Andric } 42304eeddc0SDimitry Andric 42404eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 42504eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 42604eeddc0SDimitry Andric if (Value *Val = Env.createValue(S->getType())) 42704eeddc0SDimitry Andric Env.setValue(Loc, *Val); 42804eeddc0SDimitry Andric } 42904eeddc0SDimitry Andric 43004eeddc0SDimitry Andric void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { 43104eeddc0SDimitry Andric if (S->getOperator() == OO_Equal) { 43204eeddc0SDimitry Andric assert(S->getNumArgs() == 2); 43304eeddc0SDimitry Andric 43404eeddc0SDimitry Andric const Expr *Arg0 = S->getArg(0); 43504eeddc0SDimitry Andric assert(Arg0 != nullptr); 43604eeddc0SDimitry Andric 43704eeddc0SDimitry Andric const Expr *Arg1 = S->getArg(1); 43804eeddc0SDimitry Andric assert(Arg1 != nullptr); 43904eeddc0SDimitry Andric 44004eeddc0SDimitry Andric // Evaluate only copy and move assignment operators. 44104eeddc0SDimitry Andric auto *Arg0Type = Arg0->getType()->getUnqualifiedDesugaredType(); 44204eeddc0SDimitry Andric auto *Arg1Type = Arg1->getType()->getUnqualifiedDesugaredType(); 44304eeddc0SDimitry Andric if (Arg0Type != Arg1Type) 44404eeddc0SDimitry Andric return; 44504eeddc0SDimitry Andric 44604eeddc0SDimitry Andric auto *ObjectLoc = Env.getStorageLocation(*Arg0, SkipPast::Reference); 44704eeddc0SDimitry Andric if (ObjectLoc == nullptr) 44804eeddc0SDimitry Andric return; 44904eeddc0SDimitry Andric 45004eeddc0SDimitry Andric auto *Val = Env.getValue(*Arg1, SkipPast::Reference); 45104eeddc0SDimitry Andric if (Val == nullptr) 45204eeddc0SDimitry Andric return; 45304eeddc0SDimitry Andric 45481ad6265SDimitry Andric // Assign a value to the storage location of the object. 45504eeddc0SDimitry Andric Env.setValue(*ObjectLoc, *Val); 45681ad6265SDimitry Andric 45781ad6265SDimitry Andric // FIXME: Add a test for the value of the whole expression. 45881ad6265SDimitry Andric // Assign a storage location for the whole expression. 45981ad6265SDimitry Andric Env.setStorageLocation(*S, *ObjectLoc); 46004eeddc0SDimitry Andric } 46104eeddc0SDimitry Andric } 46204eeddc0SDimitry Andric 46304eeddc0SDimitry Andric void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) { 46404eeddc0SDimitry Andric if (S->getCastKind() == CK_ConstructorConversion) { 46504eeddc0SDimitry Andric const Expr *SubExpr = S->getSubExpr(); 46604eeddc0SDimitry Andric assert(SubExpr != nullptr); 46704eeddc0SDimitry Andric 46804eeddc0SDimitry Andric auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None); 46904eeddc0SDimitry Andric if (SubExprLoc == nullptr) 47004eeddc0SDimitry Andric return; 47104eeddc0SDimitry Andric 47204eeddc0SDimitry Andric Env.setStorageLocation(*S, *SubExprLoc); 47304eeddc0SDimitry Andric } 47404eeddc0SDimitry Andric } 47504eeddc0SDimitry Andric 47604eeddc0SDimitry Andric void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) { 47704eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 47804eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 47904eeddc0SDimitry Andric if (Value *Val = Env.createValue(S->getType())) 48004eeddc0SDimitry Andric Env.setValue(Loc, *Val); 48104eeddc0SDimitry Andric } 48204eeddc0SDimitry Andric 48304eeddc0SDimitry Andric void VisitCallExpr(const CallExpr *S) { 48481ad6265SDimitry Andric // Of clang's builtins, only `__builtin_expect` is handled explicitly, since 48581ad6265SDimitry Andric // others (like trap, debugtrap, and unreachable) are handled by CFG 48681ad6265SDimitry Andric // construction. 48704eeddc0SDimitry Andric if (S->isCallToStdMove()) { 48804eeddc0SDimitry Andric assert(S->getNumArgs() == 1); 48904eeddc0SDimitry Andric 49004eeddc0SDimitry Andric const Expr *Arg = S->getArg(0); 49104eeddc0SDimitry Andric assert(Arg != nullptr); 49204eeddc0SDimitry Andric 49304eeddc0SDimitry Andric auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::None); 49404eeddc0SDimitry Andric if (ArgLoc == nullptr) 49504eeddc0SDimitry Andric return; 49604eeddc0SDimitry Andric 49704eeddc0SDimitry Andric Env.setStorageLocation(*S, *ArgLoc); 49881ad6265SDimitry Andric } else if (S->getDirectCallee() != nullptr && 49981ad6265SDimitry Andric S->getDirectCallee()->getBuiltinID() == 50081ad6265SDimitry Andric Builtin::BI__builtin_expect) { 50181ad6265SDimitry Andric assert(S->getNumArgs() > 0); 50281ad6265SDimitry Andric assert(S->getArg(0) != nullptr); 50381ad6265SDimitry Andric // `__builtin_expect` returns by-value, so strip away any potential 50481ad6265SDimitry Andric // references in the argument. 50581ad6265SDimitry Andric auto *ArgLoc = Env.getStorageLocation(*S->getArg(0), SkipPast::Reference); 50681ad6265SDimitry Andric if (ArgLoc == nullptr) 50781ad6265SDimitry Andric return; 50881ad6265SDimitry Andric Env.setStorageLocation(*S, *ArgLoc); 509*972a253aSDimitry Andric } else if (const FunctionDecl *F = S->getDirectCallee()) { 510*972a253aSDimitry Andric // This case is for context-sensitive analysis, which we only do if we 511*972a253aSDimitry Andric // have the callee body available in the translation unit. 512*972a253aSDimitry Andric if (!Options.ContextSensitive || F->getBody() == nullptr) 513*972a253aSDimitry Andric return; 514*972a253aSDimitry Andric 515*972a253aSDimitry Andric auto &ASTCtx = F->getASTContext(); 516*972a253aSDimitry Andric 517*972a253aSDimitry Andric // FIXME: Cache these CFGs. 518*972a253aSDimitry Andric auto CFCtx = ControlFlowContext::build(F, F->getBody(), &ASTCtx); 519*972a253aSDimitry Andric // FIXME: Handle errors here and below. 520*972a253aSDimitry Andric assert(CFCtx); 521*972a253aSDimitry Andric auto ExitBlock = CFCtx->getCFG().getExit().getBlockID(); 522*972a253aSDimitry Andric 523*972a253aSDimitry Andric auto CalleeEnv = Env.pushCall(S); 524*972a253aSDimitry Andric 525*972a253aSDimitry Andric // FIXME: Use the same analysis as the caller for the callee. 526*972a253aSDimitry Andric DataflowAnalysisOptions Options; 527*972a253aSDimitry Andric auto Analysis = NoopAnalysis(ASTCtx, Options); 528*972a253aSDimitry Andric 529*972a253aSDimitry Andric auto BlockToOutputState = 530*972a253aSDimitry Andric dataflow::runDataflowAnalysis(*CFCtx, Analysis, CalleeEnv); 531*972a253aSDimitry Andric assert(BlockToOutputState); 532*972a253aSDimitry Andric assert(ExitBlock < BlockToOutputState->size()); 533*972a253aSDimitry Andric 534*972a253aSDimitry Andric auto ExitState = (*BlockToOutputState)[ExitBlock]; 535*972a253aSDimitry Andric assert(ExitState); 536*972a253aSDimitry Andric 537*972a253aSDimitry Andric Env = ExitState->Env; 53804eeddc0SDimitry Andric } 53904eeddc0SDimitry Andric } 54004eeddc0SDimitry Andric 54104eeddc0SDimitry Andric void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) { 54204eeddc0SDimitry Andric const Expr *SubExpr = S->getSubExpr(); 54304eeddc0SDimitry Andric assert(SubExpr != nullptr); 54404eeddc0SDimitry Andric 54504eeddc0SDimitry Andric auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None); 54604eeddc0SDimitry Andric if (SubExprLoc == nullptr) 54704eeddc0SDimitry Andric return; 54804eeddc0SDimitry Andric 54904eeddc0SDimitry Andric Env.setStorageLocation(*S, *SubExprLoc); 55004eeddc0SDimitry Andric } 55104eeddc0SDimitry Andric 55204eeddc0SDimitry Andric void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) { 55304eeddc0SDimitry Andric const Expr *SubExpr = S->getSubExpr(); 55404eeddc0SDimitry Andric assert(SubExpr != nullptr); 55504eeddc0SDimitry Andric 55604eeddc0SDimitry Andric auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None); 55704eeddc0SDimitry Andric if (SubExprLoc == nullptr) 55804eeddc0SDimitry Andric return; 55904eeddc0SDimitry Andric 56004eeddc0SDimitry Andric Env.setStorageLocation(*S, *SubExprLoc); 56104eeddc0SDimitry Andric } 56204eeddc0SDimitry Andric 56304eeddc0SDimitry Andric void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) { 56404eeddc0SDimitry Andric if (S->getCastKind() == CK_NoOp) { 56504eeddc0SDimitry Andric const Expr *SubExpr = S->getSubExpr(); 56604eeddc0SDimitry Andric assert(SubExpr != nullptr); 56704eeddc0SDimitry Andric 56804eeddc0SDimitry Andric auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None); 56904eeddc0SDimitry Andric if (SubExprLoc == nullptr) 57004eeddc0SDimitry Andric return; 57104eeddc0SDimitry Andric 57204eeddc0SDimitry Andric Env.setStorageLocation(*S, *SubExprLoc); 57304eeddc0SDimitry Andric } 57404eeddc0SDimitry Andric } 57504eeddc0SDimitry Andric 57604eeddc0SDimitry Andric void VisitConditionalOperator(const ConditionalOperator *S) { 57704eeddc0SDimitry Andric // FIXME: Revisit this once flow conditions are added to the framework. For 57804eeddc0SDimitry Andric // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow 57904eeddc0SDimitry Andric // condition. 58004eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 58104eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 58204eeddc0SDimitry Andric if (Value *Val = Env.createValue(S->getType())) 58304eeddc0SDimitry Andric Env.setValue(Loc, *Val); 58404eeddc0SDimitry Andric } 58504eeddc0SDimitry Andric 58604eeddc0SDimitry Andric void VisitInitListExpr(const InitListExpr *S) { 58704eeddc0SDimitry Andric QualType Type = S->getType(); 58804eeddc0SDimitry Andric 58904eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 59004eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 59104eeddc0SDimitry Andric 59204eeddc0SDimitry Andric auto *Val = Env.createValue(Type); 59304eeddc0SDimitry Andric if (Val == nullptr) 59404eeddc0SDimitry Andric return; 59504eeddc0SDimitry Andric 59604eeddc0SDimitry Andric Env.setValue(Loc, *Val); 59704eeddc0SDimitry Andric 59804eeddc0SDimitry Andric if (Type->isStructureOrClassType()) { 599*972a253aSDimitry Andric for (auto It : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) { 600*972a253aSDimitry Andric const FieldDecl *Field = std::get<0>(It); 60104eeddc0SDimitry Andric assert(Field != nullptr); 60204eeddc0SDimitry Andric 603*972a253aSDimitry Andric const Expr *Init = std::get<1>(It); 60404eeddc0SDimitry Andric assert(Init != nullptr); 60504eeddc0SDimitry Andric 60604eeddc0SDimitry Andric if (Value *InitVal = Env.getValue(*Init, SkipPast::None)) 60704eeddc0SDimitry Andric cast<StructValue>(Val)->setChild(*Field, *InitVal); 60804eeddc0SDimitry Andric } 60904eeddc0SDimitry Andric } 61004eeddc0SDimitry Andric // FIXME: Implement array initialization. 61104eeddc0SDimitry Andric } 61204eeddc0SDimitry Andric 61304eeddc0SDimitry Andric void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) { 61404eeddc0SDimitry Andric auto &Loc = Env.createStorageLocation(*S); 61504eeddc0SDimitry Andric Env.setStorageLocation(*S, Loc); 61604eeddc0SDimitry Andric Env.setValue(Loc, Env.getBoolLiteralValue(S->getValue())); 61704eeddc0SDimitry Andric } 61804eeddc0SDimitry Andric 61981ad6265SDimitry Andric void VisitParenExpr(const ParenExpr *S) { 62081ad6265SDimitry Andric // The CFG does not contain `ParenExpr` as top-level statements in basic 62181ad6265SDimitry Andric // blocks, however manual traversal to sub-expressions may encounter them. 62281ad6265SDimitry Andric // Redirect to the sub-expression. 62381ad6265SDimitry Andric auto *SubExpr = S->getSubExpr(); 62481ad6265SDimitry Andric assert(SubExpr != nullptr); 62581ad6265SDimitry Andric Visit(SubExpr); 62681ad6265SDimitry Andric } 62781ad6265SDimitry Andric 62881ad6265SDimitry Andric void VisitExprWithCleanups(const ExprWithCleanups *S) { 62981ad6265SDimitry Andric // The CFG does not contain `ExprWithCleanups` as top-level statements in 63081ad6265SDimitry Andric // basic blocks, however manual traversal to sub-expressions may encounter 63181ad6265SDimitry Andric // them. Redirect to the sub-expression. 63281ad6265SDimitry Andric auto *SubExpr = S->getSubExpr(); 63381ad6265SDimitry Andric assert(SubExpr != nullptr); 63481ad6265SDimitry Andric Visit(SubExpr); 63581ad6265SDimitry Andric } 63681ad6265SDimitry Andric 63704eeddc0SDimitry Andric private: 63881ad6265SDimitry Andric BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) { 63981ad6265SDimitry Andric // `SubExpr` and its parent logic operator might be part of different basic 64081ad6265SDimitry Andric // blocks. We try to access the value that is assigned to `SubExpr` in the 64181ad6265SDimitry Andric // corresponding environment. 64281ad6265SDimitry Andric if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr)) { 64381ad6265SDimitry Andric if (auto *Val = dyn_cast_or_null<BoolValue>( 64481ad6265SDimitry Andric SubExprEnv->getValue(SubExpr, SkipPast::Reference))) 64581ad6265SDimitry Andric return *Val; 64681ad6265SDimitry Andric } 64781ad6265SDimitry Andric 64881ad6265SDimitry Andric if (Env.getStorageLocation(SubExpr, SkipPast::None) == nullptr) { 64981ad6265SDimitry Andric // Sub-expressions that are logic operators are not added in basic blocks 65081ad6265SDimitry Andric // (e.g. see CFG for `bool d = a && (b || c);`). If `SubExpr` is a logic 65181ad6265SDimitry Andric // operator, it may not have been evaluated and assigned a value yet. In 65281ad6265SDimitry Andric // that case, we need to first visit `SubExpr` and then try to get the 65381ad6265SDimitry Andric // value that gets assigned to it. 65481ad6265SDimitry Andric Visit(&SubExpr); 65581ad6265SDimitry Andric } 65681ad6265SDimitry Andric 65781ad6265SDimitry Andric if (auto *Val = dyn_cast_or_null<BoolValue>( 65881ad6265SDimitry Andric Env.getValue(SubExpr, SkipPast::Reference))) 65981ad6265SDimitry Andric return *Val; 66081ad6265SDimitry Andric 66181ad6265SDimitry Andric // If the value of `SubExpr` is still unknown, we create a fresh symbolic 66281ad6265SDimitry Andric // boolean value for it. 66381ad6265SDimitry Andric return Env.makeAtomicBoolValue(); 66481ad6265SDimitry Andric } 66581ad6265SDimitry Andric 66681ad6265SDimitry Andric const StmtToEnvMap &StmtToEnv; 66704eeddc0SDimitry Andric Environment &Env; 668*972a253aSDimitry Andric TransferOptions Options; 66904eeddc0SDimitry Andric }; 67004eeddc0SDimitry Andric 671*972a253aSDimitry Andric void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, 672*972a253aSDimitry Andric TransferOptions Options) { 673*972a253aSDimitry Andric TransferVisitor(StmtToEnv, Env, Options).Visit(&S); 67404eeddc0SDimitry Andric } 67504eeddc0SDimitry Andric 67604eeddc0SDimitry Andric } // namespace dataflow 67704eeddc0SDimitry Andric } // namespace clang 678