https://github.com/steakhal updated https://github.com/llvm/llvm-project/pull/85104
>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 1/9] 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 >From ebe3ebc5c4f5278e5578d7e3b32c8cf9a015b8be Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Wed, 13 Mar 2024 18:07:07 +0100 Subject: [PATCH 2/9] Revert unnecessary clang-format --- clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 226 +++++++++++--------- 1 file changed, 128 insertions(+), 98 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 89791bd88001e3..9e663f27efce67 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,7 +178,9 @@ 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); @@ -249,25 +251,26 @@ 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); @@ -289,9 +292,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); @@ -325,56 +328,58 @@ 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); @@ -382,12 +387,13 @@ 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); } @@ -411,7 +417,8 @@ 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); @@ -455,7 +462,9 @@ 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; @@ -491,7 +500,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 { @@ -517,7 +526,9 @@ 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() @@ -611,9 +622,13 @@ 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."); @@ -641,13 +656,17 @@ 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(); @@ -665,8 +684,7 @@ void FieldRegion::printPretty(raw_ostream &os) const { printPrettyAsExpr(os); os << "'"; } else { - os << "field " - << "\'" << getDecl()->getName() << "'"; + os << "field " << "\'" << getDecl()->getName() << "'"; } } @@ -850,7 +868,7 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, } template <typename REG> -const REG *MemRegionManager::LazyAllocate(REG *®ion) { +const REG *MemRegionManager::LazyAllocate(REG*& region) { if (!region) { region = new (A) REG(*this); } @@ -859,7 +877,7 @@ const REG *MemRegionManager::LazyAllocate(REG *®ion) { } template <typename REG, typename ARG> -const REG *MemRegionManager::LazyAllocate(REG *®ion, ARG a) { +const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) { if (!region) { region = new (A) REG(this, a); } @@ -867,7 +885,7 @@ const REG *MemRegionManager::LazyAllocate(REG *®ion, ARG a) { return region; } -const StackLocalsSpaceRegion * +const StackLocalsSpaceRegion* MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) { assert(STC); StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC]; @@ -891,9 +909,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); @@ -928,14 +946,13 @@ 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())); } @@ -1007,16 +1024,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 *>(); @@ -1030,7 +1047,8 @@ 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)) @@ -1052,10 +1070,13 @@ 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(); } } @@ -1084,14 +1105,17 @@ 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 @@ -1113,7 +1137,7 @@ const BlockDataRegion *MemRegionManager::getBlockDataRegion( return getSubRegion<BlockDataRegion>(BC, LC, blockCount, sReg); } -const CompoundLiteralRegion * +const CompoundLiteralRegion* MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL, const LocationContext *LC) { const MemSpaceRegion *sReg = nullptr; @@ -1129,17 +1153,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) { @@ -1174,19 +1198,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(); @@ -1214,7 +1238,8 @@ 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(); @@ -1232,8 +1257,10 @@ 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; @@ -1256,7 +1283,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>(); @@ -1277,7 +1304,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(); @@ -1315,15 +1342,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; } @@ -1338,7 +1365,9 @@ 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. @@ -1599,8 +1628,7 @@ 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; } @@ -1612,7 +1640,7 @@ static RegionOffset calculateOffset(const MemRegion *R) { } } -Finish: + Finish: if (SymbolicOffsetBase) return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic); return RegionOffset(R, Offset); @@ -1637,11 +1665,13 @@ 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); } @@ -1659,7 +1689,7 @@ void BlockDataRegion::LazyInitializeReferencedVars() { std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end()); if (NumBlockVars == 0) { - ReferencedVars = (void *)0x1; + ReferencedVars = (void*) 0x1; return; } @@ -1688,11 +1718,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 = @@ -1704,11 +1734,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 = >From ae1c1b262bcbc5636538446b5f2ad83959c3e6d4 Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Wed, 13 Mar 2024 18:07:45 +0100 Subject: [PATCH 3/9] Refine uses of auto --- clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 9e663f27efce67..e6ba6e0885a5f5 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -722,8 +722,8 @@ std::string MemRegion::getDescriptiveName(bool UseQuotes) const { } // Index is a SymbolVal. else if (auto SI = ER->getIndex().getAs<nonloc::SymbolVal>()) { - if (auto SR = SI->getAsSymbol()) { - if (auto OR = SR->getOriginRegion()) { + if (SymbolRef SR = SI->getAsSymbol()) { + if (const MemRegion *OR = SR->getOriginRegion()) { std::string Idx = OR->getDescriptiveName(false); ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str(); } >From 6009aeb080883dcc6c4b92c1e02a62eb54220304 Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Wed, 13 Mar 2024 18:09:01 +0100 Subject: [PATCH 4/9] Fix license comment --- clang/unittests/StaticAnalyzer/MemRegionTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/unittests/StaticAnalyzer/MemRegionTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionTest.cpp index c179f7a2c8230b..031d4932df068e 100644 --- a/clang/unittests/StaticAnalyzer/MemRegionTest.cpp +++ b/clang/unittests/StaticAnalyzer/MemRegionTest.cpp @@ -1,4 +1,4 @@ -//===- unittests/StaticAnalyzer/MemRegionTest.cpp ----------------------===// +//===- 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. >From 578108b6df50cc2027fc941781dce4b8afa1fc2b Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Wed, 13 Mar 2024 18:09:37 +0100 Subject: [PATCH 5/9] Cleanup unittest includes --- clang/unittests/StaticAnalyzer/MemRegionTest.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/clang/unittests/StaticAnalyzer/MemRegionTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionTest.cpp index 031d4932df068e..2e5e4e4acbf7f1 100644 --- a/clang/unittests/StaticAnalyzer/MemRegionTest.cpp +++ b/clang/unittests/StaticAnalyzer/MemRegionTest.cpp @@ -7,11 +7,8 @@ //===----------------------------------------------------------------------===// #include "CheckerRegistration.h" -#include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" -#include "Reusables.h" - namespace clang { namespace ento { namespace { >From f0c3fc44f685f338da2ae1d084a2e3eded635ef3 Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Wed, 13 Mar 2024 18:46:43 +0100 Subject: [PATCH 6/9] Rework testing --- .../StaticAnalyzer/MemRegionTest.cpp | 87 ++++++++++++------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/clang/unittests/StaticAnalyzer/MemRegionTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionTest.cpp index 2e5e4e4acbf7f1..e27aa8983b9d61 100644 --- a/clang/unittests/StaticAnalyzer/MemRegionTest.cpp +++ b/clang/unittests/StaticAnalyzer/MemRegionTest.cpp @@ -6,48 +6,77 @@ // //===----------------------------------------------------------------------===// +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "CheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "gtest/gtest.h" -namespace clang { -namespace ento { -namespace { +using namespace clang; +using namespace ento; -std::string MemRegName; +namespace { -class MemRegChecker : public Checker<check::Location> { +class DescriptiveNameChecker : public Checker<check::PreCall> { 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 checkPreCall(const CallEvent &Call, CheckerContext &C) const { + if (!HandlerFn.matches(Call)) + return; + + const MemRegion *ArgReg = Call.getArgSVal(0).getAsRegion(); + assert(ArgReg && "expecting a location as the first argument"); + + auto DescriptiveName = ArgReg->getDescriptiveName(/*UseQuotes=*/false); + if (ExplodedNode *Node = C.generateNonFatalErrorNode(C.getState())) { + auto Report = + std::make_unique<PathSensitiveBugReport>(Bug, DescriptiveName, Node); + C.emitReport(std::move(Report)); + } } + +private: + const BugType Bug{this, "DescriptiveNameBug"}; + const CallDescription HandlerFn = {{"reportDescriptiveName"}, 1}; }; -void addMemRegChecker(AnalysisASTConsumer &AnalysisConsumer, - AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"test.MemRegChecker", true}}; +void addDescriptiveNameChecker(AnalysisASTConsumer &AnalysisConsumer, + AnalyzerOptions &AnOpts) { + AnOpts.CheckersAndPackages = {{"DescriptiveNameChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker<MemRegChecker>("test.MemRegChecker", "Description", ""); + Registry.addChecker<DescriptiveNameChecker>("DescriptiveNameChecker", + "Desc", "DocsURI"); }); } -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(); +TEST(MemRegionDescriptiveNameTest, ConcreteIntElementRegionIndex) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +const unsigned int index = 1; +extern int array[3]; +void top() { + reportDescriptiveName(&array[index]); +})cpp"; + + std::string Output; + ASSERT_TRUE(runCheckerOnCode<addDescriptiveNameChecker>( + Code.str(), Output, /*OnlyEmitWarnings=*/true)); + EXPECT_EQ(Output, "DescriptiveNameChecker: array[1]\n"); +} + +TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndex) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +extern unsigned int index; +extern int array[3]; +void top() { + reportDescriptiveName(&array[index]); +})cpp"; + + std::string Output; + ASSERT_TRUE(runCheckerOnCode<addDescriptiveNameChecker>( + Code.str(), Output, /*OnlyEmitWarnings=*/true)); + EXPECT_EQ(Output, "DescriptiveNameChecker: array[index]\n"); } } // namespace -} // namespace ento -} // namespace clang >From bb4ee4c42b1ef327b6d6c14aba3e9ca3b73f8ed1 Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Wed, 13 Mar 2024 18:49:38 +0100 Subject: [PATCH 7/9] Rename unittest file --- clang/unittests/StaticAnalyzer/CMakeLists.txt | 2 +- .../{MemRegionTest.cpp => MemRegionDescriptiveNameTest.cpp} | 2 +- llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) rename clang/unittests/StaticAnalyzer/{MemRegionTest.cpp => MemRegionDescriptiveNameTest.cpp} (97%) diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index aede87281113da..519be36fe0fa38 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -11,7 +11,7 @@ add_clang_unittest(StaticAnalysisTests CallEventTest.cpp ConflictingEvalCallsTest.cpp FalsePositiveRefutationBRVisitorTest.cpp - MemRegionTest.cpp + MemRegionDescriptiveNameTest.cpp NoStateChangeFuncVisitorTest.cpp ParamRegionTest.cpp RangeSetTest.cpp diff --git a/clang/unittests/StaticAnalyzer/MemRegionTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp similarity index 97% rename from clang/unittests/StaticAnalyzer/MemRegionTest.cpp rename to clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp index e27aa8983b9d61..783f09500a7efb 100644 --- a/clang/unittests/StaticAnalyzer/MemRegionTest.cpp +++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp @@ -1,4 +1,4 @@ -//===- MemRegionTest.cpp --------------------------------------------------===// +//===- MemRegionDescriptiveNameTest.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn index 01c2b6ced3366f..9230ac79a48ae3 100644 --- a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn @@ -19,6 +19,7 @@ unittest("StaticAnalysisTests") { "CallEventTest.cpp", "ConflictingEvalCallsTest.cpp", "FalsePositiveRefutationBRVisitorTest.cpp", + "MemRegionDescriptiveNameTest.cpp", "NoStateChangeFuncVisitorTest.cpp", "ParamRegionTest.cpp", "RangeSetTest.cpp", >From 9c7a82264ffbebc370fdd91f7dc2869c4c488a0b Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Wed, 13 Mar 2024 18:51:37 +0100 Subject: [PATCH 8/9] Cleanup redundant code --- .../StaticAnalyzer/MemRegionDescriptiveNameTest.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp index 783f09500a7efb..39e0be17b13bdb 100644 --- a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp +++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp @@ -49,6 +49,11 @@ void addDescriptiveNameChecker(AnalysisASTConsumer &AnalysisConsumer, }); } +bool runChecker(StringRef Code, std::string &Output) { + return runCheckerOnCode<addDescriptiveNameChecker>(Code.str(), Output, + /*OnlyEmitWarnings=*/true); +} + TEST(MemRegionDescriptiveNameTest, ConcreteIntElementRegionIndex) { StringRef Code = R"cpp( void reportDescriptiveName(int *p); @@ -59,8 +64,7 @@ void top() { })cpp"; std::string Output; - ASSERT_TRUE(runCheckerOnCode<addDescriptiveNameChecker>( - Code.str(), Output, /*OnlyEmitWarnings=*/true)); + ASSERT_TRUE(runChecker(Code, Output)); EXPECT_EQ(Output, "DescriptiveNameChecker: array[1]\n"); } @@ -74,8 +78,7 @@ void top() { })cpp"; std::string Output; - ASSERT_TRUE(runCheckerOnCode<addDescriptiveNameChecker>( - Code.str(), Output, /*OnlyEmitWarnings=*/true)); + ASSERT_TRUE(runChecker(Code, Output)); EXPECT_EQ(Output, "DescriptiveNameChecker: array[index]\n"); } >From 31f5ddc2444a64effe73c96ba52b47910d24ebb0 Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Wed, 13 Mar 2024 21:13:16 +0100 Subject: [PATCH 9/9] clang-format --- clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp index 39e0be17b13bdb..402b4504f0a680 100644 --- a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp +++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp @@ -6,11 +6,11 @@ // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "CheckerRegistration.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "gtest/gtest.h" using namespace clang; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits