https://github.com/T-Gruber created https://github.com/llvm/llvm-project/pull/85104
Fixes https://github.com/llvm/llvm-project/issues/84463 Changes: - Adapted MemRegion::getDescriptiveName - Added unittest to check name for a given clang::ento::ElementRegion - Some format changes due to clang-format >From 0f964127ed91e23f8e969e08ce680535cfeb8906 Mon Sep 17 00:00:00 2001 From: Andreas Steinhausen <andreas.steinhau...@concenrio.io> Date: Wed, 13 Mar 2024 17:07:53 +0100 Subject: [PATCH] Adapted MemRegion::getDescriptiveName to handle ElementRegions --- clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 244 ++++++++---------- clang/unittests/StaticAnalyzer/CMakeLists.txt | 1 + .../StaticAnalyzer/MemRegionTest.cpp | 56 ++++ 3 files changed, 167 insertions(+), 134 deletions(-) create mode 100644 clang/unittests/StaticAnalyzer/MemRegionTest.cpp diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 16db6b249dc92b..89791bd88001e3 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -66,7 +66,7 @@ using namespace ento; //===----------------------------------------------------------------------===// template <typename RegionTy, typename SuperTy, typename Arg1Ty> -RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, +RegionTy *MemRegionManager::getSubRegion(const Arg1Ty arg1, const SuperTy *superRegion) { llvm::FoldingSetNodeID ID; RegionTy::ProfileRegion(ID, arg1, superRegion); @@ -82,7 +82,7 @@ RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, } template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty> -RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, +RegionTy *MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, const SuperTy *superRegion) { llvm::FoldingSetNodeID ID; RegionTy::ProfileRegion(ID, arg1, arg2, superRegion); @@ -97,9 +97,9 @@ RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, return R; } -template <typename RegionTy, typename SuperTy, - typename Arg1Ty, typename Arg2Ty, typename Arg3Ty> -RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, +template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty, + typename Arg3Ty> +RegionTy *MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, const Arg3Ty arg3, const SuperTy *superRegion) { llvm::FoldingSetNodeID ID; @@ -129,8 +129,8 @@ MemRegionManager::~MemRegionManager() = default; // Basic methods. //===----------------------------------------------------------------------===// -bool SubRegion::isSubRegionOf(const MemRegion* R) const { - const MemRegion* r = this; +bool SubRegion::isSubRegionOf(const MemRegion *R) const { + const MemRegion *r = this; do { if (r == R) return true; @@ -143,7 +143,7 @@ bool SubRegion::isSubRegionOf(const MemRegion* R) const { } MemRegionManager &SubRegion::getMemRegionManager() const { - const SubRegion* r = this; + const SubRegion *r = this; do { const MemRegion *superRegion = r->getSuperRegion(); if (const auto *sr = dyn_cast<SubRegion>(superRegion)) { @@ -178,9 +178,7 @@ ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg) const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { return IVD; } -QualType ObjCIvarRegion::getValueType() const { - return getDecl()->getType(); -} +QualType ObjCIvarRegion::getValueType() const { return getDecl()->getType(); } QualType CXXBaseObjectRegion::getValueType() const { return QualType(getDecl()->getTypeForDecl(), 0); @@ -251,26 +249,25 @@ void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, ID.AddPointer(superRegion); } -void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, - const Expr *Ex, unsigned cnt, - const MemRegion *superRegion) { +void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *Ex, + unsigned cnt, const MemRegion *superRegion) { ID.AddInteger(static_cast<unsigned>(AllocaRegionKind)); ID.AddPointer(Ex); ID.AddInteger(cnt); ID.AddPointer(superRegion); } -void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const { +void AllocaRegion::Profile(llvm::FoldingSetNodeID &ID) const { ProfileRegion(ID, Ex, Cnt, superRegion); } -void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const { +void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID &ID) const { CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion); } -void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, +void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const CompoundLiteralExpr *CL, - const MemRegion* superRegion) { + const MemRegion *superRegion) { ID.AddInteger(static_cast<unsigned>(CompoundLiteralRegionKind)); ID.AddPointer(CL); ID.AddPointer(superRegion); @@ -292,9 +289,9 @@ void FieldRegion::Profile(llvm::FoldingSetNodeID &ID) const { ProfileRegion(ID, getDecl(), superRegion); } -void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, +void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const ObjCIvarDecl *ivd, - const MemRegion* superRegion) { + const MemRegion *superRegion) { ID.AddInteger(static_cast<unsigned>(ObjCIvarRegionKind)); ID.AddPointer(ivd); ID.AddPointer(superRegion); @@ -328,58 +325,56 @@ void ParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const { ProfileRegion(ID, getOriginExpr(), getIndex(), superRegion); } -void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, +void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, SymbolRef sym, const MemRegion *sreg) { ID.AddInteger(static_cast<unsigned>(MemRegion::SymbolicRegionKind)); ID.Add(sym); ID.AddPointer(sreg); } -void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const { +void SymbolicRegion::Profile(llvm::FoldingSetNodeID &ID) const { SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion()); } -void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, +void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, QualType ElementType, SVal Idx, - const MemRegion* superRegion) { + const MemRegion *superRegion) { ID.AddInteger(MemRegion::ElementRegionKind); ID.Add(ElementType); ID.AddPointer(superRegion); Idx.Profile(ID); } -void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { +void ElementRegion::Profile(llvm::FoldingSetNodeID &ID) const { ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion); } -void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, - const NamedDecl *FD, - const MemRegion*) { +void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, + const NamedDecl *FD, const MemRegion *) { ID.AddInteger(MemRegion::FunctionCodeRegionKind); ID.AddPointer(FD); } -void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { +void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID &ID) const { FunctionCodeRegion::ProfileRegion(ID, FD, superRegion); } -void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, +void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const BlockDecl *BD, CanQualType, const AnalysisDeclContext *AC, - const MemRegion*) { + const MemRegion *) { ID.AddInteger(MemRegion::BlockCodeRegionKind); ID.AddPointer(BD); } -void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { +void BlockCodeRegion::Profile(llvm::FoldingSetNodeID &ID) const { BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion); } -void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, +void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const BlockCodeRegion *BC, const LocationContext *LC, - unsigned BlkCount, - const MemRegion *sReg) { + unsigned BlkCount, const MemRegion *sReg) { ID.AddInteger(MemRegion::BlockDataRegionKind); ID.AddPointer(BC); ID.AddPointer(LC); @@ -387,13 +382,12 @@ void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, ID.AddPointer(sReg); } -void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const { +void BlockDataRegion::Profile(llvm::FoldingSetNodeID &ID) const { BlockDataRegion::ProfileRegion(ID, BC, LC, BlockCount, getSuperRegion()); } void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, - Expr const *Ex, - const MemRegion *sReg) { + Expr const *Ex, const MemRegion *sReg) { ID.AddPointer(Ex); ID.AddPointer(sReg); } @@ -417,8 +411,7 @@ void CXXLifetimeExtendedObjectRegion::Profile( } void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, - const CXXRecordDecl *RD, - bool IsVirtual, + const CXXRecordDecl *RD, bool IsVirtual, const MemRegion *SReg) { ID.AddPointer(RD); ID.AddBoolean(IsVirtual); @@ -462,9 +455,7 @@ void SubRegion::anchor() {} // Region pretty-printing. //===----------------------------------------------------------------------===// -LLVM_DUMP_METHOD void MemRegion::dump() const { - dumpToStream(llvm::errs()); -} +LLVM_DUMP_METHOD void MemRegion::dump() const { dumpToStream(llvm::errs()); } std::string MemRegion::getString() const { std::string s; @@ -500,7 +491,7 @@ void BlockDataRegion::dumpToStream(raw_ostream &os) const { void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const { // FIXME: More elaborate pretty-printing. - os << "{ S" << CL->getID(getContext()) << " }"; + os << "{ S" << CL->getID(getContext()) << " }"; } void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const { @@ -526,9 +517,7 @@ void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const { os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}'; } -void CXXThisRegion::dumpToStream(raw_ostream &os) const { - os << "this"; -} +void CXXThisRegion::dumpToStream(raw_ostream &os) const { os << "this"; } void ElementRegion::dumpToStream(raw_ostream &os) const { os << "Element{" << superRegion << ',' << Index << ',' << getElementType() @@ -622,13 +611,9 @@ void ParamVarRegion::dumpToStream(raw_ostream &os) const { } } -bool MemRegion::canPrintPretty() const { - return canPrintPrettyAsExpr(); -} +bool MemRegion::canPrintPretty() const { return canPrintPrettyAsExpr(); } -bool MemRegion::canPrintPrettyAsExpr() const { - return false; -} +bool MemRegion::canPrintPrettyAsExpr() const { return false; } void MemRegion::printPretty(raw_ostream &os) const { assert(canPrintPretty() && "This region cannot be printed pretty."); @@ -656,17 +641,13 @@ void ParamVarRegion::printPrettyAsExpr(raw_ostream &os) const { os << getDecl()->getName(); } -bool ObjCIvarRegion::canPrintPrettyAsExpr() const { - return true; -} +bool ObjCIvarRegion::canPrintPrettyAsExpr() const { return true; } void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const { os << getDecl()->getName(); } -bool FieldRegion::canPrintPretty() const { - return true; -} +bool FieldRegion::canPrintPretty() const { return true; } bool FieldRegion::canPrintPrettyAsExpr() const { return superRegion->canPrintPrettyAsExpr(); @@ -684,7 +665,8 @@ void FieldRegion::printPretty(raw_ostream &os) const { printPrettyAsExpr(os); os << "'"; } else { - os << "field " << "\'" << getDecl()->getName() << "'"; + os << "field " + << "\'" << getDecl()->getName() << "'"; } } @@ -720,14 +702,20 @@ std::string MemRegion::getDescriptiveName(bool UseQuotes) const { CI->getValue().toString(Idx); ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str(); } - // If not a ConcreteInt, try to obtain the variable - // name by calling 'getDescriptiveName' recursively. - else { - std::string Idx = ER->getDescriptiveName(false); - if (!Idx.empty()) { - ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str(); + // Index is a SymbolVal. + else if (auto SI = ER->getIndex().getAs<nonloc::SymbolVal>()) { + if (auto SR = SI->getAsSymbol()) { + if (auto OR = SR->getOriginRegion()) { + std::string Idx = OR->getDescriptiveName(false); + ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str(); + } } } + // Index is neither a ConcreteInt nor SymbolVal, give up and return. + else { + assert(false && "we should have a descriptive name"); + return ""; + } R = ER->getSuperRegion(); } @@ -862,7 +850,7 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, } template <typename REG> -const REG *MemRegionManager::LazyAllocate(REG*& region) { +const REG *MemRegionManager::LazyAllocate(REG *®ion) { if (!region) { region = new (A) REG(*this); } @@ -871,7 +859,7 @@ const REG *MemRegionManager::LazyAllocate(REG*& region) { } template <typename REG, typename ARG> -const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) { +const REG *MemRegionManager::LazyAllocate(REG *®ion, ARG a) { if (!region) { region = new (A) REG(this, a); } @@ -879,7 +867,7 @@ const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) { return region; } -const StackLocalsSpaceRegion* +const StackLocalsSpaceRegion * MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) { assert(STC); StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC]; @@ -903,9 +891,9 @@ MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) { return R; } -const GlobalsSpaceRegion -*MemRegionManager::getGlobalsRegion(MemRegion::Kind K, - const CodeTextRegion *CR) { +const GlobalsSpaceRegion * +MemRegionManager::getGlobalsRegion(MemRegion::Kind K, + const CodeTextRegion *CR) { if (!CR) { if (K == MemRegion::GlobalSystemSpaceRegionKind) return LazyAllocate(SystemGlobals); @@ -940,13 +928,14 @@ const CodeSpaceRegion *MemRegionManager::getCodeRegion() { // Constructing regions. //===----------------------------------------------------------------------===// -const StringRegion *MemRegionManager::getStringRegion(const StringLiteral *Str){ +const StringRegion * +MemRegionManager::getStringRegion(const StringLiteral *Str) { return getSubRegion<StringRegion>( Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); } const ObjCStringRegion * -MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str){ +MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str) { return getSubRegion<ObjCStringRegion>( Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); } @@ -1018,16 +1007,16 @@ const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, sReg = getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind); } - // Finally handle static locals. + // Finally handle static locals. } else { // FIXME: Once we implement scope handling, we will need to properly lookup // 'D' to the proper LocationContext. const DeclContext *DC = D->getDeclContext(); llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V = - getStackOrCaptureRegionForDeclContext(LC, DC, D); + getStackOrCaptureRegionForDeclContext(LC, DC, D); - if (V.is<const VarRegion*>()) - return V.get<const VarRegion*>(); + if (V.is<const VarRegion *>()) + return V.get<const VarRegion *>(); const auto *STC = V.get<const StackFrameContext *>(); @@ -1041,8 +1030,7 @@ const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, isa<ParmVarDecl, ImplicitParamDecl>(D) ? static_cast<const MemRegion *>(getStackArgumentsRegion(STC)) : static_cast<const MemRegion *>(getStackLocalsRegion(STC)); - } - else { + } else { assert(D->isStaticLocal()); const Decl *STCD = STC->getDecl(); if (isa<FunctionDecl, ObjCMethodDecl>(STCD)) @@ -1064,13 +1052,10 @@ const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, } T = getContext().getBlockPointerType(T); - const BlockCodeRegion *BTR = - getBlockCodeRegion(BD, Ctx.getCanonicalType(T), - STC->getAnalysisDeclContext()); - sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, - BTR); - } - else { + const BlockCodeRegion *BTR = getBlockCodeRegion( + BD, Ctx.getCanonicalType(T), STC->getAnalysisDeclContext()); + sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, BTR); + } else { sReg = getGlobalsRegion(); } } @@ -1099,17 +1084,14 @@ MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index, getStackArgumentsRegion(SFC)); } -const BlockDataRegion * -MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC, - const LocationContext *LC, - unsigned blockCount) { +const BlockDataRegion *MemRegionManager::getBlockDataRegion( + const BlockCodeRegion *BC, const LocationContext *LC, unsigned blockCount) { const MemSpaceRegion *sReg = nullptr; const BlockDecl *BD = BC->getDecl(); if (!BD->hasCaptures()) { // This handles 'static' blocks. sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); - } - else { + } else { bool IsArcManagedBlock = Ctx.getLangOpts().ObjCAutoRefCount; // ARC managed blocks can be initialized on stack or directly in heap @@ -1131,7 +1113,7 @@ MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC, return getSubRegion<BlockDataRegion>(BC, LC, blockCount, sReg); } -const CompoundLiteralRegion* +const CompoundLiteralRegion * MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL, const LocationContext *LC) { const MemSpaceRegion *sReg = nullptr; @@ -1147,17 +1129,17 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL, return getSubRegion<CompoundLiteralRegion>(CL, sReg); } -const ElementRegion* +const ElementRegion * MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx, - const SubRegion* superRegion, - ASTContext &Ctx){ + const SubRegion *superRegion, + ASTContext &Ctx) { QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType(); llvm::FoldingSetNodeID ID; ElementRegion::ProfileRegion(ID, T, Idx, superRegion); void *InsertPos; - MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); + MemRegion *data = Regions.FindNodeOrInsertPos(ID, InsertPos); auto *R = cast_or_null<ElementRegion>(data); if (!R) { @@ -1192,19 +1174,19 @@ const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) { return getSubRegion<SymbolicRegion>(Sym, getHeapRegion()); } -const FieldRegion* +const FieldRegion * MemRegionManager::getFieldRegion(const FieldDecl *d, - const SubRegion* superRegion){ + const SubRegion *superRegion) { return getSubRegion<FieldRegion>(d, superRegion); } -const ObjCIvarRegion* +const ObjCIvarRegion * MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d, - const SubRegion* superRegion) { + const SubRegion *superRegion) { return getSubRegion<ObjCIvarRegion>(d, superRegion); } -const CXXTempObjectRegion* +const CXXTempObjectRegion * MemRegionManager::getCXXTempObjectRegion(Expr const *E, LocationContext const *LC) { const StackFrameContext *SFC = LC->getStackFrame(); @@ -1232,8 +1214,7 @@ MemRegionManager::getCXXStaticLifetimeExtendedObjectRegion( /// Checks whether \p BaseClass is a valid virtual or direct non-virtual base /// class of the type of \p Super. static bool isValidBaseClass(const CXXRecordDecl *BaseClass, - const TypedValueRegion *Super, - bool IsVirtual) { + const TypedValueRegion *Super, bool IsVirtual) { BaseClass = BaseClass->getCanonicalDecl(); const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl(); @@ -1251,10 +1232,8 @@ static bool isValidBaseClass(const CXXRecordDecl *BaseClass, return false; } -const CXXBaseObjectRegion * -MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD, - const SubRegion *Super, - bool IsVirtual) { +const CXXBaseObjectRegion *MemRegionManager::getCXXBaseObjectRegion( + const CXXRecordDecl *RD, const SubRegion *Super, bool IsVirtual) { if (isa<TypedValueRegion>(Super)) { assert(isValidBaseClass(RD, cast<TypedValueRegion>(Super), IsVirtual)); (void)&isValidBaseClass; @@ -1277,7 +1256,7 @@ MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD, return getSubRegion<CXXDerivedObjectRegion>(RD, Super); } -const CXXThisRegion* +const CXXThisRegion * MemRegionManager::getCXXThisRegion(QualType thisPointerTy, const LocationContext *LC) { const auto *PT = thisPointerTy->getAs<PointerType>(); @@ -1298,7 +1277,7 @@ MemRegionManager::getCXXThisRegion(QualType thisPointerTy, return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC)); } -const AllocaRegion* +const AllocaRegion * MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt, const LocationContext *LC) { const StackFrameContext *STC = LC->getStackFrame(); @@ -1336,15 +1315,15 @@ const MemRegion *MemRegion::getBaseRegion() const { const MemRegion *R = this; while (true) { switch (R->getKind()) { - case MemRegion::ElementRegionKind: - case MemRegion::FieldRegionKind: - case MemRegion::ObjCIvarRegionKind: - case MemRegion::CXXBaseObjectRegionKind: - case MemRegion::CXXDerivedObjectRegionKind: - R = cast<SubRegion>(R)->getSuperRegion(); - continue; - default: - break; + case MemRegion::ElementRegionKind: + case MemRegion::FieldRegionKind: + case MemRegion::ObjCIvarRegionKind: + case MemRegion::CXXBaseObjectRegionKind: + case MemRegion::CXXDerivedObjectRegionKind: + R = cast<SubRegion>(R)->getSuperRegion(); + continue; + default: + break; } break; } @@ -1359,9 +1338,7 @@ const MemRegion *MemRegion::getMostDerivedObjectRegion() const { return R; } -bool MemRegion::isSubRegionOf(const MemRegion *) const { - return false; -} +bool MemRegion::isSubRegionOf(const MemRegion *) const { return false; } //===----------------------------------------------------------------------===// // View handling. @@ -1622,7 +1599,8 @@ static RegionOffset calculateOffset(const MemRegion *R) { // Get the field number. unsigned idx = 0; for (RecordDecl::field_iterator FI = RD->field_begin(), - FE = RD->field_end(); FI != FE; ++FI, ++idx) { + FE = RD->field_end(); + FI != FE; ++FI, ++idx) { if (FR->getDecl() == *FI) break; } @@ -1634,7 +1612,7 @@ static RegionOffset calculateOffset(const MemRegion *R) { } } - Finish: +Finish: if (SymbolicOffsetBase) return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic); return RegionOffset(R, Offset); @@ -1659,13 +1637,11 @@ BlockDataRegion::getCaptureRegions(const VarDecl *VD) { if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) { VR = MemMgr.getNonParamVarRegion(VD, this); OriginalVR = MemMgr.getVarRegion(VD, LC); - } - else { + } else { if (LC) { VR = MemMgr.getVarRegion(VD, LC); OriginalVR = VR; - } - else { + } else { VR = MemMgr.getNonParamVarRegion(VD, MemMgr.getUnknownRegion()); OriginalVR = MemMgr.getVarRegion(VD, LC); } @@ -1683,7 +1659,7 @@ void BlockDataRegion::LazyInitializeReferencedVars() { std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end()); if (NumBlockVars == 0) { - ReferencedVars = (void*) 0x1; + ReferencedVars = (void *)0x1; return; } @@ -1712,11 +1688,11 @@ void BlockDataRegion::LazyInitializeReferencedVars() { BlockDataRegion::referenced_vars_iterator BlockDataRegion::referenced_vars_begin() const { - const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); + const_cast<BlockDataRegion *>(this)->LazyInitializeReferencedVars(); auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars); - if (Vec == (void*) 0x1) + if (Vec == (void *)0x1) return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); auto *VecOriginal = @@ -1728,11 +1704,11 @@ BlockDataRegion::referenced_vars_begin() const { BlockDataRegion::referenced_vars_iterator BlockDataRegion::referenced_vars_end() const { - const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); + const_cast<BlockDataRegion *>(this)->LazyInitializeReferencedVars(); auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars); - if (Vec == (void*) 0x1) + if (Vec == (void *)0x1) return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); auto *VecOriginal = diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index 775f0f8486b8f9..aede87281113da 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_unittest(StaticAnalysisTests CallEventTest.cpp ConflictingEvalCallsTest.cpp FalsePositiveRefutationBRVisitorTest.cpp + MemRegionTest.cpp NoStateChangeFuncVisitorTest.cpp ParamRegionTest.cpp RangeSetTest.cpp diff --git a/clang/unittests/StaticAnalyzer/MemRegionTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionTest.cpp new file mode 100644 index 00000000000000..c179f7a2c8230b --- /dev/null +++ b/clang/unittests/StaticAnalyzer/MemRegionTest.cpp @@ -0,0 +1,56 @@ +//===- unittests/StaticAnalyzer/MemRegionTest.cpp ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CheckerRegistration.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +#include "Reusables.h" + +namespace clang { +namespace ento { +namespace { + +std::string MemRegName; + +class MemRegChecker : public Checker<check::Location> { +public: + void checkLocation(const SVal &Loc, bool IsLoad, const Stmt *S, + CheckerContext &CC) const { + if (const MemRegion *MemReg = Loc.getAsRegion()) + MemRegName = MemReg->getDescriptiveName(false); + } +}; + +void addMemRegChecker(AnalysisASTConsumer &AnalysisConsumer, + AnalyzerOptions &AnOpts) { + AnOpts.CheckersAndPackages = {{"test.MemRegChecker", true}}; + AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { + Registry.addChecker<MemRegChecker>("test.MemRegChecker", "Description", ""); + }); +} + +TEST(MemRegion, DescriptiveName) { + EXPECT_TRUE(runCheckerOnCode<addMemRegChecker>( + "const unsigned int index = 1; " + "extern int array[3]; " + "int main() { int a = array[index]; return 0; }")); + EXPECT_EQ(MemRegName, "array[1]"); + MemRegName.clear(); + + EXPECT_TRUE(runCheckerOnCode<addMemRegChecker>( + "extern unsigned int index; " + "extern int array[3]; " + "int main() { int a = array[index]; return 0; }")); + EXPECT_EQ(MemRegName, "array[index]"); + MemRegName.clear(); +} + +} // namespace +} // namespace ento +} // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits