[PATCH] D79704: [Analyzer] [NFC] Parameter Regions
Artem Dergachev via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue May 12 13:28:21 PDT 2020
NoQ added a comment.
Blanket reply! `ParamRegion` is not a `DeclRegion` because it does not necessarily have a corresponding `Decl`. For instance, when calling a function through an unknown function pointer, you don't have the declaration of a function, let alone its parameters. But for parameters of C++ object type you still need your `ParamRegion` because arguments are constructed into it.
================
Comment at: clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h:1051
+
+ const Expr *OriginExpr;
+ unsigned Index;
----------------
baloghadamsoftware wrote:
> We do not use this at all. However, if I remove it then tests begin to fail with strange reasons, some of them even crashes at strange points. It seems that we need this for profiling the subclass.
`Profile` is completely essential. Without it different regions will be treated as if it's the same region.
================
Comment at: clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h:1054-1055
+
+ ParamRegion(const Expr *OE, unsigned Idx, const MemRegion *SReg)
+ : TypedValueRegion(SReg, ParamRegionKind), OriginExpr(OE), Index(Idx) {}
+
----------------
It looks like you decided to keep `VarRegion` for the top frame.
I want that asserted here, in the constructor, so that never to make a mistake on this front.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp:197-198
+ if (const ParamRegion *PR = R->getAs<ParamRegion>())
+ if (const StackArgumentsSpaceRegion *
+ stackReg = dyn_cast<StackArgumentsSpaceRegion>(PR->getMemorySpace()))
+ if (stackReg->getStackFrame() == SFC)
----------------
Yes it is a `StackArgumentsSpaceRegion`! Because we're a parameter.
================
Comment at: clang/lib/StaticAnalyzer/Core/MemRegion.cpp:164
+ const auto *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
+ return SSR ? SSR->getStackFrame() : nullptr;
+}
----------------
`SSR` shouldn't ever be null. Any parameter must be on the stack.
================
Comment at: clang/lib/StaticAnalyzer/Core/MemRegion.cpp:1579-1584
+ std::tie(Call, Index) = ParamRegion::getExprAndIndexForParam(PVD, LC);
+
+ if (Call)
+ OriginalVR = MemMgr.getParamRegion(Call, Index, LC);
+ else
+ OriginalVR = MemMgr.getVarRegion(VD, LC);
----------------
I suggest making a function in `MemRegionManager` that takes a `Decl` and returns a region. There should only be one place in the code that decides when exactly do we produce a `ParamRegion` instead of a `VarRegion`.
================
Comment at: clang/lib/StaticAnalyzer/Core/MemRegion.cpp:1732
+ const LocationContext *LC) {
+ unsigned Index = PVD->getFunctionScopeIndex();
+ const StackFrameContext *SFC = LC->getStackFrame();
----------------
Does this method also suffer from the parameter vs. argument off-by-one problem with operators?
================
Comment at: clang/lib/StaticAnalyzer/Core/MemRegion.cpp:1735-1736
+ const Stmt *CallSite = SFC->getCallSite();
+ if (!CallSite)
+ return std::make_pair(nullptr, UINT_MAX);
+
----------------
Does this actually ever happen?
================
Comment at: clang/lib/StaticAnalyzer/Core/MemRegion.cpp:1740
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (Index >= FD->param_size() || FD->parameters()[Index] != PVD)
+ return std::make_pair(nullptr, UINT_MAX);
----------------
Why would that ever happen? If it's just a sanity check, it should be an assertion.
================
Comment at: clang/lib/StaticAnalyzer/Core/RegionStore.cpp:2031
+
+ assert (isa<StackArgumentsSpaceRegion>(MS));
+
----------------
Let's simply make a blanket assertion in `ParamRegion`'s constructor.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D79704/new/
https://reviews.llvm.org/D79704
More information about the cfe-commits
mailing list