1218887Sdim// SValBuilder.cpp - Basic class for all SValBuilder implementations -*- C++ -*- 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// This file defines SValBuilder, the base class for all (complete) SValBuilder 11218887Sdim// implementations. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14218887Sdim 15249423Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 16249423Sdim#include "clang/AST/DeclCXX.h" 17234353Sdim#include "clang/AST/ExprCXX.h" 18249423Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" 19218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 20249423Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 21218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 22218887Sdim 23218887Sdimusing namespace clang; 24218887Sdimusing namespace ento; 25218887Sdim 26218887Sdim//===----------------------------------------------------------------------===// 27218887Sdim// Basic SVal creation. 28218887Sdim//===----------------------------------------------------------------------===// 29218887Sdim 30234353Sdimvoid SValBuilder::anchor() { } 31234353Sdim 32221345SdimDefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) { 33221345Sdim if (Loc::isLocType(type)) 34218887Sdim return makeNull(); 35218887Sdim 36251662Sdim if (type->isIntegralOrEnumerationType()) 37221345Sdim return makeIntVal(0, type); 38218887Sdim 39218887Sdim // FIXME: Handle floats. 40218887Sdim // FIXME: Handle structs. 41218887Sdim return UnknownVal(); 42218887Sdim} 43218887Sdim 44218887SdimNonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, 45221345Sdim const llvm::APSInt& rhs, QualType type) { 46218887Sdim // The Environment ensures we always get a persistent APSInt in 47218887Sdim // BasicValueFactory, so we don't need to get the APSInt from 48218887Sdim // BasicValueFactory again. 49234353Sdim assert(lhs); 50221345Sdim assert(!Loc::isLocType(type)); 51234353Sdim return nonloc::SymbolVal(SymMgr.getSymIntExpr(lhs, op, rhs, type)); 52218887Sdim} 53218887Sdim 54234353SdimNonLoc SValBuilder::makeNonLoc(const llvm::APSInt& lhs, 55234353Sdim BinaryOperator::Opcode op, const SymExpr *rhs, 56234353Sdim QualType type) { 57234353Sdim assert(rhs); 58234353Sdim assert(!Loc::isLocType(type)); 59234353Sdim return nonloc::SymbolVal(SymMgr.getIntSymExpr(lhs, op, rhs, type)); 60234353Sdim} 61234353Sdim 62218887SdimNonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, 63221345Sdim const SymExpr *rhs, QualType type) { 64234353Sdim assert(lhs && rhs); 65221345Sdim assert(!Loc::isLocType(type)); 66234353Sdim return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type)); 67218887Sdim} 68218887Sdim 69234353SdimNonLoc SValBuilder::makeNonLoc(const SymExpr *operand, 70234353Sdim QualType fromTy, QualType toTy) { 71234353Sdim assert(operand); 72234353Sdim assert(!Loc::isLocType(toTy)); 73234353Sdim return nonloc::SymbolVal(SymMgr.getCastSymbol(operand, fromTy, toTy)); 74234353Sdim} 75218887Sdim 76221345SdimSVal SValBuilder::convertToArrayIndex(SVal val) { 77221345Sdim if (val.isUnknownOrUndef()) 78221345Sdim return val; 79218887Sdim 80218887Sdim // Common case: we have an appropriately sized integer. 81249423Sdim if (Optional<nonloc::ConcreteInt> CI = val.getAs<nonloc::ConcreteInt>()) { 82218887Sdim const llvm::APSInt& I = CI->getValue(); 83218887Sdim if (I.getBitWidth() == ArrayIndexWidth && I.isSigned()) 84221345Sdim return val; 85218887Sdim } 86218887Sdim 87249423Sdim return evalCastFromNonLoc(val.castAs<NonLoc>(), ArrayIndexTy); 88218887Sdim} 89218887Sdim 90234353Sdimnonloc::ConcreteInt SValBuilder::makeBoolVal(const CXXBoolLiteralExpr *boolean){ 91234353Sdim return makeTruthVal(boolean->getValue()); 92234353Sdim} 93234353Sdim 94218887SdimDefinedOrUnknownSVal 95226633SdimSValBuilder::getRegionValueSymbolVal(const TypedValueRegion* region) { 96221345Sdim QualType T = region->getValueType(); 97218887Sdim 98218887Sdim if (!SymbolManager::canSymbolicate(T)) 99218887Sdim return UnknownVal(); 100218887Sdim 101221345Sdim SymbolRef sym = SymMgr.getRegionValueSymbol(region); 102218887Sdim 103218887Sdim if (Loc::isLocType(T)) 104218887Sdim return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); 105218887Sdim 106218887Sdim return nonloc::SymbolVal(sym); 107218887Sdim} 108218887Sdim 109251662SdimDefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag, 110251662Sdim const Expr *Ex, 111243830Sdim const LocationContext *LCtx, 112251662Sdim unsigned Count) { 113251662Sdim QualType T = Ex->getType(); 114251662Sdim 115251662Sdim // Compute the type of the result. If the expression is not an R-value, the 116251662Sdim // result should be a location. 117251662Sdim QualType ExType = Ex->getType(); 118251662Sdim if (Ex->isGLValue()) 119251662Sdim T = LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType); 120251662Sdim 121251662Sdim return conjureSymbolVal(SymbolTag, Ex, LCtx, T, Count); 122234353Sdim} 123218887Sdim 124243830SdimDefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag, 125243830Sdim const Expr *expr, 126243830Sdim const LocationContext *LCtx, 127243830Sdim QualType type, 128243830Sdim unsigned count) { 129234353Sdim if (!SymbolManager::canSymbolicate(type)) 130218887Sdim return UnknownVal(); 131218887Sdim 132243830Sdim SymbolRef sym = SymMgr.conjureSymbol(expr, LCtx, type, count, symbolTag); 133218887Sdim 134234353Sdim if (Loc::isLocType(type)) 135218887Sdim return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); 136218887Sdim 137218887Sdim return nonloc::SymbolVal(sym); 138218887Sdim} 139218887Sdim 140234353Sdim 141243830SdimDefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt, 142243830Sdim const LocationContext *LCtx, 143243830Sdim QualType type, 144243830Sdim unsigned visitCount) { 145221345Sdim if (!SymbolManager::canSymbolicate(type)) 146218887Sdim return UnknownVal(); 147218887Sdim 148243830Sdim SymbolRef sym = SymMgr.conjureSymbol(stmt, LCtx, type, visitCount); 149234353Sdim 150221345Sdim if (Loc::isLocType(type)) 151218887Sdim return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); 152234353Sdim 153218887Sdim return nonloc::SymbolVal(sym); 154218887Sdim} 155218887Sdim 156239462SdimDefinedOrUnknownSVal 157239462SdimSValBuilder::getConjuredHeapSymbolVal(const Expr *E, 158239462Sdim const LocationContext *LCtx, 159239462Sdim unsigned VisitCount) { 160239462Sdim QualType T = E->getType(); 161239462Sdim assert(Loc::isLocType(T)); 162239462Sdim assert(SymbolManager::canSymbolicate(T)); 163239462Sdim 164243830Sdim SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount); 165239462Sdim return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym)); 166239462Sdim} 167239462Sdim 168221345SdimDefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag, 169221345Sdim const MemRegion *region, 170221345Sdim const Expr *expr, QualType type, 171221345Sdim unsigned count) { 172221345Sdim assert(SymbolManager::canSymbolicate(type) && "Invalid metadata symbol type"); 173218887Sdim 174221345Sdim SymbolRef sym = 175221345Sdim SymMgr.getMetadataSymbol(region, expr, type, count, symbolTag); 176218887Sdim 177221345Sdim if (Loc::isLocType(type)) 178218887Sdim return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); 179218887Sdim 180218887Sdim return nonloc::SymbolVal(sym); 181218887Sdim} 182218887Sdim 183218887SdimDefinedOrUnknownSVal 184218887SdimSValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, 185226633Sdim const TypedValueRegion *region) { 186221345Sdim QualType T = region->getValueType(); 187218887Sdim 188218887Sdim if (!SymbolManager::canSymbolicate(T)) 189218887Sdim return UnknownVal(); 190218887Sdim 191221345Sdim SymbolRef sym = SymMgr.getDerivedSymbol(parentSymbol, region); 192218887Sdim 193218887Sdim if (Loc::isLocType(T)) 194218887Sdim return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); 195218887Sdim 196218887Sdim return nonloc::SymbolVal(sym); 197218887Sdim} 198218887Sdim 199226633SdimDefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl *func) { 200221345Sdim return loc::MemRegionVal(MemMgr.getFunctionTextRegion(func)); 201218887Sdim} 202218887Sdim 203221345SdimDefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block, 204221345Sdim CanQualType locTy, 205263508Sdim const LocationContext *locContext, 206263508Sdim unsigned blockCount) { 207218887Sdim const BlockTextRegion *BC = 208234353Sdim MemMgr.getBlockTextRegion(block, locTy, locContext->getAnalysisDeclContext()); 209263508Sdim const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, locContext, 210263508Sdim blockCount); 211218887Sdim return loc::MemRegionVal(BD); 212218887Sdim} 213218887Sdim 214239462Sdim/// Return a memory region for the 'this' object reference. 215239462Sdimloc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D, 216239462Sdim const StackFrameContext *SFC) { 217239462Sdim return loc::MemRegionVal(getRegionManager(). 218239462Sdim getCXXThisRegion(D->getThisType(getContext()), SFC)); 219239462Sdim} 220239462Sdim 221239462Sdim/// Return a memory region for the 'this' object reference. 222239462Sdimloc::MemRegionVal SValBuilder::getCXXThis(const CXXRecordDecl *D, 223239462Sdim const StackFrameContext *SFC) { 224239462Sdim const Type *T = D->getTypeForDecl(); 225239462Sdim QualType PT = getContext().getPointerType(QualType(T, 0)); 226239462Sdim return loc::MemRegionVal(getRegionManager().getCXXThisRegion(PT, SFC)); 227239462Sdim} 228239462Sdim 229251662SdimOptional<SVal> SValBuilder::getConstantVal(const Expr *E) { 230251662Sdim E = E->IgnoreParens(); 231251662Sdim 232251662Sdim switch (E->getStmtClass()) { 233251662Sdim // Handle expressions that we treat differently from the AST's constant 234251662Sdim // evaluator. 235251662Sdim case Stmt::AddrLabelExprClass: 236251662Sdim return makeLoc(cast<AddrLabelExpr>(E)); 237251662Sdim 238251662Sdim case Stmt::CXXScalarValueInitExprClass: 239251662Sdim case Stmt::ImplicitValueInitExprClass: 240251662Sdim return makeZeroVal(E->getType()); 241251662Sdim 242251662Sdim case Stmt::ObjCStringLiteralClass: { 243251662Sdim const ObjCStringLiteral *SL = cast<ObjCStringLiteral>(E); 244251662Sdim return makeLoc(getRegionManager().getObjCStringRegion(SL)); 245251662Sdim } 246251662Sdim 247251662Sdim case Stmt::StringLiteralClass: { 248251662Sdim const StringLiteral *SL = cast<StringLiteral>(E); 249251662Sdim return makeLoc(getRegionManager().getStringRegion(SL)); 250251662Sdim } 251251662Sdim 252251662Sdim // Fast-path some expressions to avoid the overhead of going through the AST's 253251662Sdim // constant evaluator 254251662Sdim case Stmt::CharacterLiteralClass: { 255251662Sdim const CharacterLiteral *C = cast<CharacterLiteral>(E); 256251662Sdim return makeIntVal(C->getValue(), C->getType()); 257251662Sdim } 258251662Sdim 259251662Sdim case Stmt::CXXBoolLiteralExprClass: 260251662Sdim return makeBoolVal(cast<CXXBoolLiteralExpr>(E)); 261251662Sdim 262251662Sdim case Stmt::IntegerLiteralClass: 263251662Sdim return makeIntVal(cast<IntegerLiteral>(E)); 264251662Sdim 265251662Sdim case Stmt::ObjCBoolLiteralExprClass: 266251662Sdim return makeBoolVal(cast<ObjCBoolLiteralExpr>(E)); 267251662Sdim 268251662Sdim case Stmt::CXXNullPtrLiteralExprClass: 269251662Sdim return makeNull(); 270251662Sdim 271263508Sdim case Stmt::ImplicitCastExprClass: { 272263508Sdim const CastExpr *CE = cast<CastExpr>(E); 273263508Sdim if (CE->getCastKind() == CK_ArrayToPointerDecay) { 274263508Sdim Optional<SVal> ArrayVal = getConstantVal(CE->getSubExpr()); 275263508Sdim if (!ArrayVal) 276263508Sdim return None; 277263508Sdim return evalCast(*ArrayVal, CE->getType(), CE->getSubExpr()->getType()); 278263508Sdim } 279263508Sdim // FALLTHROUGH 280263508Sdim } 281263508Sdim 282251662Sdim // If we don't have a special case, fall back to the AST's constant evaluator. 283251662Sdim default: { 284251662Sdim // Don't try to come up with a value for materialized temporaries. 285251662Sdim if (E->isGLValue()) 286251662Sdim return None; 287251662Sdim 288251662Sdim ASTContext &Ctx = getContext(); 289251662Sdim llvm::APSInt Result; 290251662Sdim if (E->EvaluateAsInt(Result, Ctx)) 291251662Sdim return makeIntVal(Result); 292251662Sdim 293251662Sdim if (Loc::isLocType(E->getType())) 294251662Sdim if (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull)) 295251662Sdim return makeNull(); 296251662Sdim 297251662Sdim return None; 298251662Sdim } 299251662Sdim } 300251662Sdim} 301251662Sdim 302218887Sdim//===----------------------------------------------------------------------===// 303218887Sdim 304239462SdimSVal SValBuilder::makeSymExprValNN(ProgramStateRef State, 305239462Sdim BinaryOperator::Opcode Op, 306239462Sdim NonLoc LHS, NonLoc RHS, 307239462Sdim QualType ResultTy) { 308239462Sdim if (!State->isTainted(RHS) && !State->isTainted(LHS)) 309239462Sdim return UnknownVal(); 310239462Sdim 311239462Sdim const SymExpr *symLHS = LHS.getAsSymExpr(); 312239462Sdim const SymExpr *symRHS = RHS.getAsSymExpr(); 313239462Sdim // TODO: When the Max Complexity is reached, we should conjure a symbol 314239462Sdim // instead of generating an Unknown value and propagate the taint info to it. 315239462Sdim const unsigned MaxComp = 10000; // 100000 28X 316234353Sdim 317239462Sdim if (symLHS && symRHS && 318239462Sdim (symLHS->computeComplexity() + symRHS->computeComplexity()) < MaxComp) 319239462Sdim return makeNonLoc(symLHS, Op, symRHS, ResultTy); 320239462Sdim 321239462Sdim if (symLHS && symLHS->computeComplexity() < MaxComp) 322249423Sdim if (Optional<nonloc::ConcreteInt> rInt = RHS.getAs<nonloc::ConcreteInt>()) 323234353Sdim return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy); 324234353Sdim 325239462Sdim if (symRHS && symRHS->computeComplexity() < MaxComp) 326249423Sdim if (Optional<nonloc::ConcreteInt> lInt = LHS.getAs<nonloc::ConcreteInt>()) 327234353Sdim return makeNonLoc(lInt->getValue(), Op, symRHS, ResultTy); 328234353Sdim 329234353Sdim return UnknownVal(); 330234353Sdim} 331234353Sdim 332234353Sdim 333234353SdimSVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, 334221345Sdim SVal lhs, SVal rhs, QualType type) { 335218887Sdim 336221345Sdim if (lhs.isUndef() || rhs.isUndef()) 337218887Sdim return UndefinedVal(); 338218887Sdim 339221345Sdim if (lhs.isUnknown() || rhs.isUnknown()) 340218887Sdim return UnknownVal(); 341218887Sdim 342249423Sdim if (Optional<Loc> LV = lhs.getAs<Loc>()) { 343249423Sdim if (Optional<Loc> RV = rhs.getAs<Loc>()) 344249423Sdim return evalBinOpLL(state, op, *LV, *RV, type); 345218887Sdim 346249423Sdim return evalBinOpLN(state, op, *LV, rhs.castAs<NonLoc>(), type); 347218887Sdim } 348218887Sdim 349249423Sdim if (Optional<Loc> RV = rhs.getAs<Loc>()) { 350218887Sdim // Support pointer arithmetic where the addend is on the left 351218887Sdim // and the pointer on the right. 352221345Sdim assert(op == BO_Add); 353218887Sdim 354218887Sdim // Commute the operands. 355249423Sdim return evalBinOpLN(state, op, *RV, lhs.castAs<NonLoc>(), type); 356218887Sdim } 357218887Sdim 358249423Sdim return evalBinOpNN(state, op, lhs.castAs<NonLoc>(), rhs.castAs<NonLoc>(), 359249423Sdim type); 360218887Sdim} 361218887Sdim 362234353SdimDefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state, 363221345Sdim DefinedOrUnknownSVal lhs, 364221345Sdim DefinedOrUnknownSVal rhs) { 365249423Sdim return evalBinOp(state, BO_EQ, lhs, rhs, Context.IntTy) 366249423Sdim .castAs<DefinedOrUnknownSVal>(); 367218887Sdim} 368218887Sdim 369234353Sdim/// Recursively check if the pointer types are equal modulo const, volatile, 370249423Sdim/// and restrict qualifiers. Also, assume that all types are similar to 'void'. 371249423Sdim/// Assumes the input types are canonical. 372249423Sdimstatic bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy, 373249423Sdim QualType FromTy) { 374249423Sdim while (Context.UnwrapSimilarPointerTypes(ToTy, FromTy)) { 375234353Sdim Qualifiers Quals1, Quals2; 376249423Sdim ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1); 377249423Sdim FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2); 378234353Sdim 379234353Sdim // Make sure that non cvr-qualifiers the other qualifiers (e.g., address 380234353Sdim // spaces) are identical. 381234353Sdim Quals1.removeCVRQualifiers(); 382234353Sdim Quals2.removeCVRQualifiers(); 383234353Sdim if (Quals1 != Quals2) 384234353Sdim return false; 385234353Sdim } 386234353Sdim 387249423Sdim // If we are casting to void, the 'From' value can be used to represent the 388249423Sdim // 'To' value. 389249423Sdim if (ToTy->isVoidType()) 390249423Sdim return true; 391249423Sdim 392249423Sdim if (ToTy != FromTy) 393234353Sdim return false; 394234353Sdim 395234353Sdim return true; 396234353Sdim} 397234353Sdim 398218887Sdim// FIXME: should rewrite according to the cast kind. 399218887SdimSVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) { 400234353Sdim castTy = Context.getCanonicalType(castTy); 401234353Sdim originalTy = Context.getCanonicalType(originalTy); 402218887Sdim if (val.isUnknownOrUndef() || castTy == originalTy) 403218887Sdim return val; 404218887Sdim 405251662Sdim if (castTy->isBooleanType()) { 406251662Sdim if (val.isUnknownOrUndef()) 407251662Sdim return val; 408251662Sdim if (val.isConstant()) 409251662Sdim return makeTruthVal(!val.isZeroConstant(), castTy); 410263508Sdim if (!Loc::isLocType(originalTy) && 411263508Sdim !originalTy->isIntegralOrEnumerationType() && 412263508Sdim !originalTy->isMemberPointerType()) 413263508Sdim return UnknownVal(); 414263508Sdim if (SymbolRef Sym = val.getAsSymbol(true)) { 415251662Sdim BasicValueFactory &BVF = getBasicValueFactory(); 416251662Sdim // FIXME: If we had a state here, we could see if the symbol is known to 417251662Sdim // be zero, but we don't. 418251662Sdim return makeNonLoc(Sym, BO_NE, BVF.getValue(0, Sym->getType()), castTy); 419251662Sdim } 420263508Sdim // Loc values are not always true, they could be weakly linked functions. 421263508Sdim if (Optional<Loc> L = val.getAs<Loc>()) 422263508Sdim return evalCastFromLoc(*L, castTy); 423251662Sdim 424263508Sdim Loc L = val.castAs<nonloc::LocAsInteger>().getLoc(); 425263508Sdim return evalCastFromLoc(L, castTy); 426251662Sdim } 427251662Sdim 428249423Sdim // For const casts, casts to void, just propagate the value. 429218887Sdim if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType()) 430249423Sdim if (shouldBeModeledWithNoOp(Context, Context.getPointerType(castTy), 431249423Sdim Context.getPointerType(originalTy))) 432218887Sdim return val; 433218887Sdim 434218887Sdim // Check for casts from pointers to integers. 435251662Sdim if (castTy->isIntegralOrEnumerationType() && Loc::isLocType(originalTy)) 436249423Sdim return evalCastFromLoc(val.castAs<Loc>(), castTy); 437218887Sdim 438218887Sdim // Check for casts from integers to pointers. 439251662Sdim if (Loc::isLocType(castTy) && originalTy->isIntegralOrEnumerationType()) { 440249423Sdim if (Optional<nonloc::LocAsInteger> LV = val.getAs<nonloc::LocAsInteger>()) { 441218887Sdim if (const MemRegion *R = LV->getLoc().getAsRegion()) { 442218887Sdim StoreManager &storeMgr = StateMgr.getStoreManager(); 443218887Sdim R = storeMgr.castRegion(R, castTy); 444218887Sdim return R ? SVal(loc::MemRegionVal(R)) : UnknownVal(); 445218887Sdim } 446218887Sdim return LV->getLoc(); 447218887Sdim } 448234353Sdim return dispatchCast(val, castTy); 449218887Sdim } 450218887Sdim 451218887Sdim // Just pass through function and block pointers. 452218887Sdim if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) { 453218887Sdim assert(Loc::isLocType(castTy)); 454218887Sdim return val; 455218887Sdim } 456218887Sdim 457218887Sdim // Check for casts from array type to another type. 458263508Sdim if (const ArrayType *arrayT = 459263508Sdim dyn_cast<ArrayType>(originalTy.getCanonicalType())) { 460218887Sdim // We will always decay to a pointer. 461263508Sdim QualType elemTy = arrayT->getElementType(); 462263508Sdim val = StateMgr.ArrayToPointer(val.castAs<Loc>(), elemTy); 463218887Sdim 464218887Sdim // Are we casting from an array to a pointer? If so just pass on 465218887Sdim // the decayed value. 466239462Sdim if (castTy->isPointerType() || castTy->isReferenceType()) 467218887Sdim return val; 468218887Sdim 469218887Sdim // Are we casting from an array to an integer? If so, cast the decayed 470218887Sdim // pointer value to an integer. 471251662Sdim assert(castTy->isIntegralOrEnumerationType()); 472218887Sdim 473218887Sdim // FIXME: Keep these here for now in case we decide soon that we 474218887Sdim // need the original decayed type. 475218887Sdim // QualType elemTy = cast<ArrayType>(originalTy)->getElementType(); 476218887Sdim // QualType pointerTy = C.getPointerType(elemTy); 477249423Sdim return evalCastFromLoc(val.castAs<Loc>(), castTy); 478218887Sdim } 479218887Sdim 480218887Sdim // Check for casts from a region to a specific type. 481218887Sdim if (const MemRegion *R = val.getAsRegion()) { 482239462Sdim // Handle other casts of locations to integers. 483251662Sdim if (castTy->isIntegralOrEnumerationType()) 484239462Sdim return evalCastFromLoc(loc::MemRegionVal(R), castTy); 485239462Sdim 486218887Sdim // FIXME: We should handle the case where we strip off view layers to get 487218887Sdim // to a desugared type. 488218887Sdim if (!Loc::isLocType(castTy)) { 489218887Sdim // FIXME: There can be gross cases where one casts the result of a function 490218887Sdim // (that returns a pointer) to some other value that happens to fit 491218887Sdim // within that pointer value. We currently have no good way to 492218887Sdim // model such operations. When this happens, the underlying operation 493218887Sdim // is that the caller is reasoning about bits. Conceptually we are 494218887Sdim // layering a "view" of a location on top of those bits. Perhaps 495218887Sdim // we need to be more lazy about mutual possible views, even on an 496218887Sdim // SVal? This may be necessary for bit-level reasoning as well. 497218887Sdim return UnknownVal(); 498218887Sdim } 499218887Sdim 500218887Sdim // We get a symbolic function pointer for a dereference of a function 501218887Sdim // pointer, but it is of function type. Example: 502218887Sdim 503218887Sdim // struct FPRec { 504218887Sdim // void (*my_func)(int * x); 505218887Sdim // }; 506218887Sdim // 507218887Sdim // int bar(int x); 508218887Sdim // 509218887Sdim // int f1_a(struct FPRec* foo) { 510218887Sdim // int x; 511218887Sdim // (*foo->my_func)(&x); 512218887Sdim // return bar(x)+1; // no-warning 513218887Sdim // } 514218887Sdim 515218887Sdim assert(Loc::isLocType(originalTy) || originalTy->isFunctionType() || 516218887Sdim originalTy->isBlockPointerType() || castTy->isReferenceType()); 517218887Sdim 518218887Sdim StoreManager &storeMgr = StateMgr.getStoreManager(); 519218887Sdim 520218887Sdim // Delegate to store manager to get the result of casting a region to a 521218887Sdim // different type. If the MemRegion* returned is NULL, this expression 522218887Sdim // Evaluates to UnknownVal. 523218887Sdim R = storeMgr.castRegion(R, castTy); 524218887Sdim return R ? SVal(loc::MemRegionVal(R)) : UnknownVal(); 525218887Sdim } 526218887Sdim 527234353Sdim return dispatchCast(val, castTy); 528218887Sdim} 529