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
