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

via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 18 08:25:19 PDT 2024


https://github.com/T-Gruber updated https://github.com/llvm/llvm-project/pull/85104

>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 01/12] 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

>From ebe3ebc5c4f5278e5578d7e3b32c8cf9a015b8be Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Wed, 13 Mar 2024 18:07:07 +0100
Subject: [PATCH 02/12] 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 *&region) {
+const REG *MemRegionManager::LazyAllocate(REG*& region) {
   if (!region) {
     region = new (A) REG(*this);
   }
@@ -859,7 +877,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);
   }
@@ -867,7 +885,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];
@@ -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 <benicsbalazs at gmail.com>
Date: Wed, 13 Mar 2024 18:07:45 +0100
Subject: [PATCH 03/12] 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 <benicsbalazs at gmail.com>
Date: Wed, 13 Mar 2024 18:09:01 +0100
Subject: [PATCH 04/12] 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 <benicsbalazs at gmail.com>
Date: Wed, 13 Mar 2024 18:09:37 +0100
Subject: [PATCH 05/12] 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 <benicsbalazs at gmail.com>
Date: Wed, 13 Mar 2024 18:46:43 +0100
Subject: [PATCH 06/12] 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 <benicsbalazs at gmail.com>
Date: Wed, 13 Mar 2024 18:49:38 +0100
Subject: [PATCH 07/12] 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 <benicsbalazs at gmail.com>
Date: Wed, 13 Mar 2024 18:51:37 +0100
Subject: [PATCH 08/12] 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 <benicsbalazs at gmail.com>
Date: Wed, 13 Mar 2024 21:13:16 +0100
Subject: [PATCH 09/12] 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;

>From c1caaea6c6a9091f259929d7166e4fd1cdcb519b Mon Sep 17 00:00:00 2001
From: Andreas Steinhausen <andreas.steinhausen at concenrio.io>
Date: Fri, 15 Mar 2024 09:24:14 +0100
Subject: [PATCH 10/12] Extended else branch to handle symbolics in a better
 way & added corresponding unittest test cases

---
 clang/lib/StaticAnalyzer/Core/MemRegion.cpp   | 26 +++++------
 .../MemRegionDescriptiveNameTest.cpp          | 43 +++++++++++++++++++
 2 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index e6ba6e0885a5f5..a8e573f7982b12 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -720,19 +720,21 @@ std::string MemRegion::getDescriptiveName(bool UseQuotes) const {
       CI->getValue().toString(Idx);
       ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str();
     }
-    // Index is a SymbolVal.
-    else if (auto SI = ER->getIndex().getAs<nonloc::SymbolVal>()) {
-      if (SymbolRef SR = SI->getAsSymbol()) {
-        if (const MemRegion *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.
+    // Index is symbolic, but may have a descriptive name.
     else {
-      assert(false && "we should have a descriptive name");
-      return "";
+      auto SI = ER->getIndex().getAs<nonloc::SymbolVal>();
+      if (!SI)
+        return "";
+
+      const MemRegion *OR = SI->getAsSymbol()->getOriginRegion();
+      if (!OR)
+        return "";
+
+      std::string Idx = OR->getDescriptiveName(false);
+      if (Idx.empty())
+        return "";
+
+      ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str();
     }
     R = ER->getSuperRegion();
   }
diff --git a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
index 402b4504f0a680..49d5ad406ba66b 100644
--- a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
+++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
@@ -12,6 +12,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
 #include "gtest/gtest.h"
+#include <fstream>
 
 using namespace clang;
 using namespace ento;
@@ -82,4 +83,46 @@ void top() {
   EXPECT_EQ(Output, "DescriptiveNameChecker: array[index]\n");
 }
 
+TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexSymbolValFails) {
+  StringRef Code = R"cpp(
+void reportDescriptiveName(int *p);
+extern int* ptr;
+extern int array[3];
+void top() {
+  reportDescriptiveName(&array[(long)ptr]);
+})cpp";
+
+  std::string Output;
+  ASSERT_TRUE(runChecker(Code, Output));
+  EXPECT_EQ(Output, "DescriptiveNameChecker: \n");
+}
+
+TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexOrigRegionFails) {
+  StringRef Code = R"cpp(
+void reportDescriptiveName(int *p);
+extern int getInt(void);
+extern int array[3];
+void top() {
+  reportDescriptiveName(&array[getInt()]);
+})cpp";
+
+  std::string Output;
+  ASSERT_TRUE(runChecker(Code, Output));
+  EXPECT_EQ(Output, "DescriptiveNameChecker: \n");
+}
+
+TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexDescrNameFails) {
+  StringRef Code = R"cpp(
+void reportDescriptiveName(int *p);
+extern int *ptr;
+extern int array[3];
+void top() {
+  reportDescriptiveName(&array[*ptr]);
+})cpp";
+
+  std::string Output;
+  ASSERT_TRUE(runChecker(Code, Output));
+  EXPECT_EQ(Output, "DescriptiveNameChecker: \n");
+}
+
 } // namespace

>From ed80a81f7769c7d3c66c7572ada605b49ac7f895 Mon Sep 17 00:00:00 2001
From: Andreas Steinhausen <andreas.steinhausen at concenrio.io>
Date: Mon, 18 Mar 2024 16:17:00 +0100
Subject: [PATCH 11/12] Added test case that leads to an incorrect index due to
 the use of getOriginRegion

---
 .../MemRegionDescriptiveNameTest.cpp            | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
index 49d5ad406ba66b..4cc8fbb26e8ec4 100644
--- a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
+++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
@@ -125,4 +125,21 @@ void top() {
   EXPECT_EQ(Output, "DescriptiveNameChecker: \n");
 }
 
+TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexIncorrectSymbolName) {
+  StringRef Code = R"cpp(
+void reportDescriptiveName(int *p);
+extern int x, y;
+extern int array[3];
+void top() {
+  y = x;
+  reportDescriptiveName(&array[y]);
+})cpp";
+
+  std::string Output;
+  ASSERT_TRUE(runChecker(Code, Output));
+  //FIXME: Should return array[y], but returns array[x] (OriginRegion). 
+  EXPECT_EQ(Output, "DescriptiveNameChecker: array[x]\n");
+
+}
+
 } // namespace

>From 0f2f226017fa074fe5cbe3468f965c29d30e4a99 Mon Sep 17 00:00:00 2001
From: Andreas Steinhausen <andreas.steinhausen at concenrio.io>
Date: Mon, 18 Mar 2024 16:24:47 +0100
Subject: [PATCH 12/12] Adapted format

---
 .../StaticAnalyzer/MemRegionDescriptiveNameTest.cpp         | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
index 4cc8fbb26e8ec4..ba0c4d25e13b4d 100644
--- a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
+++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
@@ -125,7 +125,8 @@ void top() {
   EXPECT_EQ(Output, "DescriptiveNameChecker: \n");
 }
 
-TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexIncorrectSymbolName) {
+TEST(MemRegionDescriptiveNameTest,
+     SymbolicElementRegionIndexIncorrectSymbolName) {
   StringRef Code = R"cpp(
 void reportDescriptiveName(int *p);
 extern int x, y;
@@ -137,9 +138,8 @@ void top() {
 
   std::string Output;
   ASSERT_TRUE(runChecker(Code, Output));
-  //FIXME: Should return array[y], but returns array[x] (OriginRegion). 
+  // FIXME: Should return array[y], but returns array[x] (OriginRegion).
   EXPECT_EQ(Output, "DescriptiveNameChecker: array[x]\n");
-
 }
 
 } // namespace



More information about the cfe-commits mailing list