[clang] Adapted MemRegion::getDescriptiveName to handle ElementRegions (PR #85104)

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 13 09:14:01 PDT 2024


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.steinhausen at 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 *&region) {
   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 *&region, 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



More information about the cfe-commits mailing list