diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/MemRegion.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 296 |
1 files changed, 205 insertions, 91 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index a10d7e69ad7e7..455adf53ac99b 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -142,7 +142,7 @@ bool SubRegion::isSubRegionOf(const MemRegion* R) const { return false; } -MemRegionManager* SubRegion::getMemRegionManager() const { +MemRegionManager &SubRegion::getMemRegionManager() const { const SubRegion* r = this; do { const MemRegion *superRegion = r->getSuperRegion(); @@ -159,62 +159,10 @@ const StackFrameContext *VarRegion::getStackFrame() const { return SSR ? SSR->getStackFrame() : nullptr; } -//===----------------------------------------------------------------------===// -// Region extents. -//===----------------------------------------------------------------------===// - -DefinedOrUnknownSVal TypedValueRegion::getExtent(SValBuilder &svalBuilder) const { - ASTContext &Ctx = svalBuilder.getContext(); - QualType T = getDesugaredValueType(Ctx); - - if (isa<VariableArrayType>(T)) - return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); - if (T->isIncompleteType()) - return UnknownVal(); - - CharUnits size = Ctx.getTypeSizeInChars(T); - QualType sizeTy = svalBuilder.getArrayIndexType(); - return svalBuilder.makeIntVal(size.getQuantity(), sizeTy); -} - -DefinedOrUnknownSVal FieldRegion::getExtent(SValBuilder &svalBuilder) const { - // Force callers to deal with bitfields explicitly. - if (getDecl()->isBitField()) - return UnknownVal(); - - DefinedOrUnknownSVal Extent = DeclRegion::getExtent(svalBuilder); - - // A zero-length array at the end of a struct often stands for dynamically- - // allocated extra memory. - if (Extent.isZeroConstant()) { - QualType T = getDesugaredValueType(svalBuilder.getContext()); - - if (isa<ConstantArrayType>(T)) - return UnknownVal(); - } - - return Extent; -} - -DefinedOrUnknownSVal AllocaRegion::getExtent(SValBuilder &svalBuilder) const { - return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); -} - -DefinedOrUnknownSVal SymbolicRegion::getExtent(SValBuilder &svalBuilder) const { - return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); -} - -DefinedOrUnknownSVal StringRegion::getExtent(SValBuilder &svalBuilder) const { - return svalBuilder.makeIntVal(getStringLiteral()->getByteLength()+1, - svalBuilder.getArrayIndexType()); -} - ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg) - : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {} + : DeclRegion(sReg, ObjCIvarRegionKind), IVD(ivd) {} -const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { - return cast<ObjCIvarDecl>(D); -} +const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { return IVD; } QualType ObjCIvarRegion::getValueType() const { return getDecl()->getType(); @@ -228,6 +176,33 @@ QualType CXXDerivedObjectRegion::getValueType() const { return QualType(getDecl()->getTypeForDecl(), 0); } +QualType ParamVarRegion::getValueType() const { + assert(getDecl() && + "`ParamVarRegion` support functions without `Decl` not implemented" + " yet."); + return getDecl()->getType(); +} + +const ParmVarDecl *ParamVarRegion::getDecl() const { + const Decl *D = getStackFrame()->getDecl(); + + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + assert(Index < FD->param_size()); + return FD->parameters()[Index]; + } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { + assert(Index < BD->param_size()); + return BD->parameters()[Index]; + } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { + assert(Index < MD->param_size()); + return MD->parameters()[Index]; + } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) { + assert(Index < CD->param_size()); + return CD->parameters()[Index]; + } else { + llvm_unreachable("Unexpected Decl kind!"); + } +} + //===----------------------------------------------------------------------===// // FoldingSet profiling. //===----------------------------------------------------------------------===// @@ -299,25 +274,44 @@ void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const { CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion); } +void FieldRegion::Profile(llvm::FoldingSetNodeID &ID) const { + ProfileRegion(ID, getDecl(), superRegion); +} + void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd, const MemRegion* superRegion) { - DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind); + ID.AddInteger(static_cast<unsigned>(ObjCIvarRegionKind)); + ID.AddPointer(ivd); + ID.AddPointer(superRegion); } -void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D, - const MemRegion* superRegion, Kind k) { - ID.AddInteger(static_cast<unsigned>(k)); - ID.AddPointer(D); +void ObjCIvarRegion::Profile(llvm::FoldingSetNodeID &ID) const { + ProfileRegion(ID, getDecl(), superRegion); +} + +void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, + const VarDecl *VD, + const MemRegion *superRegion) { + ID.AddInteger(static_cast<unsigned>(NonParamVarRegionKind)); + ID.AddPointer(VD); ID.AddPointer(superRegion); } -void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const { - DeclRegion::ProfileRegion(ID, D, superRegion, getKind()); +void NonParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const { + ProfileRegion(ID, getDecl(), superRegion); } -void VarRegion::Profile(llvm::FoldingSetNodeID &ID) const { - VarRegion::ProfileRegion(ID, getDecl(), superRegion); +void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE, + unsigned Idx, const MemRegion *SReg) { + ID.AddInteger(static_cast<unsigned>(ParamVarRegionKind)); + ID.AddPointer(OE); + ID.AddInteger(Idx); + ID.AddPointer(SReg); +} + +void ParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const { + ProfileRegion(ID, getOriginExpr(), getIndex(), superRegion); } void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, @@ -529,12 +523,11 @@ void SymbolicRegion::dumpToStream(raw_ostream &os) const { os << "SymRegion{" << sym << '}'; } -void VarRegion::dumpToStream(raw_ostream &os) const { - const auto *VD = cast<VarDecl>(D); +void NonParamVarRegion::dumpToStream(raw_ostream &os) const { if (const IdentifierInfo *ID = VD->getIdentifier()) os << ID->getName(); else - os << "VarRegion{D" << VD->getID() << '}'; + os << "NonParamVarRegion{D" << VD->getID() << '}'; } LLVM_DUMP_METHOD void RegionRawOffset::dump() const { @@ -581,6 +574,18 @@ void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const { os << "StackLocalsSpaceRegion"; } +void ParamVarRegion::dumpToStream(raw_ostream &os) const { + const ParmVarDecl *PVD = getDecl(); + assert(PVD && + "`ParamVarRegion` support functions without `Decl` not implemented" + " yet."); + if (const IdentifierInfo *ID = PVD->getIdentifier()) { + os << ID->getName(); + } else { + os << "ParamVarRegion{P" << PVD->getID() << '}'; + } +} + bool MemRegion::canPrintPretty() const { return canPrintPrettyAsExpr(); } @@ -600,11 +605,18 @@ void MemRegion::printPrettyAsExpr(raw_ostream &) const { llvm_unreachable("This region cannot be printed pretty."); } -bool VarRegion::canPrintPrettyAsExpr() const { - return true; +bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; } + +void NonParamVarRegion::printPrettyAsExpr(raw_ostream &os) const { + os << getDecl()->getName(); } -void VarRegion::printPrettyAsExpr(raw_ostream &os) const { +bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; } + +void ParamVarRegion::printPrettyAsExpr(raw_ostream &os) const { + assert(getDecl() && + "`ParamVarRegion` support functions without `Decl` not implemented" + " yet."); os << getDecl()->getName(); } @@ -717,11 +729,79 @@ SourceRange MemRegion::sourceRange() const { // MemRegionManager methods. //===----------------------------------------------------------------------===// +static DefinedOrUnknownSVal getTypeSize(QualType Ty, ASTContext &Ctx, + SValBuilder &SVB) { + CharUnits Size = Ctx.getTypeSizeInChars(Ty); + QualType SizeTy = SVB.getArrayIndexType(); + return SVB.makeIntVal(Size.getQuantity(), SizeTy); +} + +DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, + SValBuilder &SVB) const { + const auto *SR = cast<SubRegion>(MR); + SymbolManager &SymMgr = SVB.getSymbolManager(); + + switch (SR->getKind()) { + case MemRegion::AllocaRegionKind: + case MemRegion::SymbolicRegionKind: + return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR)); + case MemRegion::StringRegionKind: + return SVB.makeIntVal( + cast<StringRegion>(SR)->getStringLiteral()->getByteLength() + 1, + SVB.getArrayIndexType()); + case MemRegion::CompoundLiteralRegionKind: + case MemRegion::CXXBaseObjectRegionKind: + case MemRegion::CXXDerivedObjectRegionKind: + case MemRegion::CXXTempObjectRegionKind: + case MemRegion::CXXThisRegionKind: + case MemRegion::ObjCIvarRegionKind: + case MemRegion::NonParamVarRegionKind: + case MemRegion::ParamVarRegionKind: + case MemRegion::ElementRegionKind: + case MemRegion::ObjCStringRegionKind: { + QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx); + if (isa<VariableArrayType>(Ty)) + return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR)); + + if (Ty->isIncompleteType()) + return UnknownVal(); + + return getTypeSize(Ty, Ctx, SVB); + } + case MemRegion::FieldRegionKind: { + // Force callers to deal with bitfields explicitly. + if (cast<FieldRegion>(SR)->getDecl()->isBitField()) + return UnknownVal(); + + QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx); + DefinedOrUnknownSVal Size = getTypeSize(Ty, Ctx, SVB); + + // A zero-length array at the end of a struct often stands for dynamically + // allocated extra memory. + if (Size.isZeroConstant()) { + if (isa<ConstantArrayType>(Ty)) + return UnknownVal(); + } + + return Size; + } + // FIXME: The following are being used in 'SimpleSValBuilder' and in + // 'ArrayBoundChecker::checkLocation' because there is no symbol to + // represent the regions more appropriately. + case MemRegion::BlockDataRegionKind: + case MemRegion::BlockCodeRegionKind: + case MemRegion::FunctionCodeRegionKind: + return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR)); + default: + llvm_unreachable("Unhandled region"); + } +} + template <typename REG> const REG *MemRegionManager::LazyAllocate(REG*& region) { if (!region) { region = A.Allocate<REG>(); - new (region) REG(this); + new (region) REG(*this); } return region; @@ -746,7 +826,7 @@ MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) { return R; R = A.Allocate<StackLocalsSpaceRegion>(); - new (R) StackLocalsSpaceRegion(this, STC); + new (R) StackLocalsSpaceRegion(*this, STC); return R; } @@ -759,7 +839,7 @@ MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) { return R; R = A.Allocate<StackArgumentsSpaceRegion>(); - new (R) StackArgumentsSpaceRegion(this, STC); + new (R) StackArgumentsSpaceRegion(*this, STC); return R; } @@ -781,7 +861,7 @@ const GlobalsSpaceRegion return R; R = A.Allocate<StaticGlobalSpaceRegion>(); - new (R) StaticGlobalSpaceRegion(this, CR); + new (R) StaticGlobalSpaceRegion(*this, CR); return R; } @@ -825,15 +905,16 @@ getStackOrCaptureRegionForDeclContext(const LocationContext *LC, return SFC; } if (const auto *BC = dyn_cast<BlockInvocationContext>(LC)) { - const auto *BR = - static_cast<const BlockDataRegion *>(BC->getContextData()); + const auto *BR = static_cast<const BlockDataRegion *>(BC->getData()); // FIXME: This can be made more efficient. for (BlockDataRegion::referenced_vars_iterator I = BR->referenced_vars_begin(), E = BR->referenced_vars_end(); I != E; ++I) { - const VarRegion *VR = I.getOriginalRegion(); - if (VR->getDecl() == VD) - return cast<VarRegion>(I.getCapturedRegion()); + const TypedValueRegion *OrigR = I.getOriginalRegion(); + if (const auto *VR = dyn_cast<VarRegion>(OrigR)) { + if (VR->getDecl() == VD) + return cast<VarRegion>(I.getCapturedRegion()); + } } } @@ -842,15 +923,37 @@ getStackOrCaptureRegionForDeclContext(const LocationContext *LC, return (const StackFrameContext *)nullptr; } -const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, +const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, const LocationContext *LC) { + const auto *PVD = dyn_cast<ParmVarDecl>(D); + if (PVD) { + unsigned Index = PVD->getFunctionScopeIndex(); + const StackFrameContext *SFC = LC->getStackFrame(); + const Stmt *CallSite = SFC->getCallSite(); + if (CallSite) { + const Decl *D = SFC->getDecl(); + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + if (Index < FD->param_size() && FD->parameters()[Index] == PVD) + return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index, + getStackArgumentsRegion(SFC)); + } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { + if (Index < BD->param_size() && BD->parameters()[Index] == PVD) + return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index, + getStackArgumentsRegion(SFC)); + } else { + return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index, + getStackArgumentsRegion(SFC)); + } + } + } + D = D->getCanonicalDecl(); const MemRegion *sReg = nullptr; if (D->hasGlobalStorage() && !D->isStaticLocal()) { // First handle the globals defined in system headers. - if (C.getSourceManager().isInSystemHeader(D->getLocation())) { + if (Ctx.getSourceManager().isInSystemHeader(D->getLocation())) { // Whitelist the system globals which often DO GET modified, assume the // rest are immutable. if (D->getName().find("errno") != StringRef::npos) @@ -914,7 +1017,7 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, T = getContext().getBlockPointerType(T); const BlockCodeRegion *BTR = - getBlockCodeRegion(BD, C.getCanonicalType(T), + getBlockCodeRegion(BD, Ctx.getCanonicalType(T), STC->getAnalysisDeclContext()); sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, BTR); @@ -926,13 +1029,23 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, } } - return getSubRegion<VarRegion>(D, sReg); + return getSubRegion<NonParamVarRegion>(D, sReg); } -const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, - const MemRegion *superR) { +const NonParamVarRegion * +MemRegionManager::getNonParamVarRegion(const VarDecl *D, + const MemRegion *superR) { D = D->getCanonicalDecl(); - return getSubRegion<VarRegion>(D, superR); + return getSubRegion<NonParamVarRegion>(D, superR); +} + +const ParamVarRegion * +MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index, + const LocationContext *LC) { + const StackFrameContext *SFC = LC->getStackFrame(); + assert(SFC); + return getSubRegion<ParamVarRegion>(OriginExpr, Index, + getStackArgumentsRegion(SFC)); } const BlockDataRegion * @@ -1325,7 +1438,8 @@ static RegionOffset calculateOffset(const MemRegion *R) { case MemRegion::CXXThisRegionKind: case MemRegion::StringRegionKind: case MemRegion::ObjCStringRegionKind: - case MemRegion::VarRegionKind: + case MemRegion::NonParamVarRegionKind: + case MemRegion::ParamVarRegionKind: case MemRegion::CXXTempObjectRegionKind: // Usual base regions. goto Finish; @@ -1476,12 +1590,12 @@ RegionOffset MemRegion::getAsOffset() const { std::pair<const VarRegion *, const VarRegion *> BlockDataRegion::getCaptureRegions(const VarDecl *VD) { - MemRegionManager &MemMgr = *getMemRegionManager(); + MemRegionManager &MemMgr = getMemRegionManager(); const VarRegion *VR = nullptr; const VarRegion *OriginalVR = nullptr; if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) { - VR = MemMgr.getVarRegion(VD, this); + VR = MemMgr.getNonParamVarRegion(VD, this); OriginalVR = MemMgr.getVarRegion(VD, LC); } else { @@ -1490,7 +1604,7 @@ BlockDataRegion::getCaptureRegions(const VarDecl *VD) { OriginalVR = VR; } else { - VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion()); + VR = MemMgr.getNonParamVarRegion(VD, MemMgr.getUnknownRegion()); OriginalVR = MemMgr.getVarRegion(VD, LC); } } @@ -1511,7 +1625,7 @@ void BlockDataRegion::LazyInitializeReferencedVars() { return; } - MemRegionManager &MemMgr = *getMemRegionManager(); + MemRegionManager &MemMgr = getMemRegionManager(); llvm::BumpPtrAllocator &A = MemMgr.getAllocator(); BumpVectorContext BC(A); |