https://github.com/tahadostifam created 
https://github.com/llvm/llvm-project/pull/181948

# Added Abstract VAList region normalization into MemRegionManager
Component: `clang` `static analyzer`

The Clang Static Analyzer's `VAListChecker` currently contains **checker-local 
logic** to normalize va_list memory regions (handling ElementRegion wrappers). 
This logic is marked with:


> TODO: In the future this should be abstracted away by the analyzer.

At 
[VAListChecker.cpp](https://github.com/llvm/llvm-project/blob/main/clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp#L179)

I implemented a small abstraction in MemRegionManager and adjusted 
VAListChecker to use it. The change compiles and basic analyzer runs with 
--analyze work as expected.

## Changes

- New helper in MemRegionManager

In `clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h`

```cpp
/// Strips ElementRegion wrappers from VA lists
/// Returning canonical base region.
MemRegion *getVAListRegion(const MemRegion *Reg);
```

In `clang/lib/StaticAnalyzer/Core/MemRegion.cpp`:

```cpp
MemRegion *MemRegionManager::getVAListRegion(const MemRegion *Reg) {
  if (!Reg) return nullptr;

  if (const ElementRegion *EReg = dyn_cast<ElementRegion>(Reg)) {
    return getVAListRegion(EReg->getSuperRegion());
  }

  if (const DeclRegion *DeclReg = dyn_cast<DeclRegion>(Reg)) {
    if (isa<ParmVarDecl>(DeclReg->getDecl())) {
      return const_cast<MemRegion*>(Reg);
    }
  }

  return const_cast<MemRegion*>(Reg);
}
```

- And now VAListChecker uses engine helper method

In clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp:

```cpp
const MemRegion *VAListChecker::getVAListAsRegion(SVal SV, const Expr *E,
                                                  CheckerContext &C) const {
  const MemRegion *Reg = SV.getAsRegion();
  if (!Reg)
    return nullptr;

  MemRegionManager &MRMgr = Reg->getMemRegionManager();
  return MRMgr.getVAListRegion(Reg);
}
```

The previous checker-local logic that inspected `CastExpr`, `ParmVarDecl`, and 
`ElementRegion` has been removed.

## Small test cases

I used a small `va_list`-based example to test the new getVAListRegion logic:

```cpp
#include <stdarg.h>

void test_array_model(va_list ap) {
  char *p = (char *)ap;
  *p = 0;
}

void foo(va_list args) {
  char *p = (char *)args;
  *p = 0;
}

void test_nested(va_list ap) {
  char (*arr)[1] = (char (*)[1])ap;
  (*arr)[0] = 0;
}

int main() {
  return 0;
}
```

Built and analyzed with my patched Clang:

```bash
./bin/clang --analyze va_list_test.c
```

The analyzer runs successfully on this test, and the VAList-related code paths 
work without crashes or unexpected diagnostics.

>From 840c5688410a9c50853f286f68f9f394d7f128b5 Mon Sep 17 00:00:00 2001
From: "Taha. Dostifam" <[email protected]>
Date: Wed, 18 Feb 2026 02:08:20 +0330
Subject: [PATCH 1/2] [clang][analyzer] Add MemRegionManager::getVAListRegion()

---
 .../Core/PathSensitive/MemRegion.h            |  4 ++++
 .../StaticAnalyzer/Checkers/VAListChecker.cpp | 19 +++++--------------
 clang/lib/StaticAnalyzer/Core/MemRegion.cpp   | 16 ++++++++++++++++
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index c59413abc352d..1cd2ea9324755 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -133,6 +133,10 @@ class MemRegion : public llvm::FoldingSetNode {
     return dyn_cast<MemSpace>(getRawMemorySpace());
   }
 
+  /// Strips ElementRegion wrappers from VA lists
+  /// Returning canonical base region.
+  MemRegion *getVAListRegion(const MemRegion *Reg);
+
   /// Returns the most specific memory space for this memory region in the 
given
   /// ProgramStateRef. We may infer a more accurate memory space for unknown
   /// space regions and associate this in the State.
diff --git a/clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp
index 503fa5de868f2..0041c714e13ca 100644
--- a/clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp
@@ -176,20 +176,11 @@ const MemRegion *VAListChecker::getVAListAsRegion(SVal 
SV, const Expr *E,
   const MemRegion *Reg = SV.getAsRegion();
   if (!Reg)
     return nullptr;
-  // TODO: In the future this should be abstracted away by the analyzer.
-  bool VAListModelledAsArray = false;
-  if (const auto *Cast = dyn_cast<CastExpr>(E)) {
-    QualType Ty = Cast->getType();
-    VAListModelledAsArray =
-        Ty->isPointerType() && Ty->getPointeeType()->isRecordType();
-  }
-  if (const auto *DeclReg = Reg->getAs<DeclRegion>()) {
-    if (isa<ParmVarDecl>(DeclReg->getDecl()))
-      Reg = C.getState()->getSVal(SV.castAs<Loc>()).getAsRegion();
-  }
-  // Some VarRegion based VA lists reach here as ElementRegions.
-  const auto *EReg = dyn_cast_or_null<ElementRegion>(Reg);
-  return (EReg && VAListModelledAsArray) ? EReg->getSuperRegion() : Reg;
+
+  return C.getAnalysisManager()
+      .getRegionStore()
+      .getMemRegionManager()
+      .getVAListRegion(Reg);
 }
 
 void VAListChecker::checkPreStmt(const VAArgExpr *VAA,
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp 
b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index f20e79ae675a4..7c1dcccd9fec7 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -1888,3 +1888,19 @@ bool RegionAndSymbolInvalidationTraits::hasTrait(const 
MemRegion *MR,
 
   return false;
 }
+
+MemRegion *MemRegionManager::getVAListRegion(const MemRegion *Reg) {
+  if (!Reg) return nullptr;
+
+  if (const ElementRegion *EReg = dyn_cast<ElementRegion>(Reg)) {
+    return getVAListRegion(EReg->getSuperRegion());
+  }
+
+  if (const DeclRegion *DeclReg = dyn_cast<DeclRegion>(Reg)) {
+    if (isa<ParmVarDecl>(DeclReg->getDecl())) {
+      return const_cast<MemRegion*>(Reg);
+    }
+  }
+
+  return const_cast<MemRegion*>(Reg);
+}
\ No newline at end of file

>From b06739eaf0e2db514475feb62a7b4eb4bb46afaf Mon Sep 17 00:00:00 2001
From: "Taha. Dostifam" <[email protected]>
Date: Wed, 18 Feb 2026 04:28:36 +0330
Subject: [PATCH 2/2] [clang][analyzer] Fix MemRegionManager::getVAListRegion()

---
 .../clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h   | 8 ++++----
 clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp       | 6 ++----
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 1cd2ea9324755..925f75d65dac7 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -133,10 +133,6 @@ class MemRegion : public llvm::FoldingSetNode {
     return dyn_cast<MemSpace>(getRawMemorySpace());
   }
 
-  /// Strips ElementRegion wrappers from VA lists
-  /// Returning canonical base region.
-  MemRegion *getVAListRegion(const MemRegion *Reg);
-
   /// Returns the most specific memory space for this memory region in the 
given
   /// ProgramStateRef. We may infer a more accurate memory space for unknown
   /// space regions and associate this in the State.
@@ -1608,6 +1604,10 @@ class MemRegionManager {
   getCXXDerivedObjectRegion(const CXXRecordDecl *BaseClass,
                             const SubRegion *Super);
 
+  /// Strips ElementRegion wrappers from VA lists
+  /// Returning canonical base region.
+  MemRegion *getVAListRegion(const MemRegion *Reg);
+
   const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD);
   const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,
                                             CanQualType locTy,
diff --git a/clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp
index 0041c714e13ca..321ba2d21059e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/VAListChecker.cpp
@@ -177,10 +177,8 @@ const MemRegion *VAListChecker::getVAListAsRegion(SVal SV, 
const Expr *E,
   if (!Reg)
     return nullptr;
 
-  return C.getAnalysisManager()
-      .getRegionStore()
-      .getMemRegionManager()
-      .getVAListRegion(Reg);
+  MemRegionManager &MRMgr = Reg->getMemRegionManager();
+  return MRMgr.getVAListRegion(Reg);
 }
 
 void VAListChecker::checkPreStmt(const VAArgExpr *VAA,

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to