[PATCH] D84736: [analyzer][RFC] Handle pointer difference of ElementRegion and SymbolicRegion
Balázs Benics via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 28 07:42:07 PDT 2020
steakhal created this revision.
steakhal added reviewers: NoQ, vsavchenko, martong, baloghadamsoftware, ASDenysPetrov, xazax.hun, Szelethus.
Herald added subscribers: cfe-commits, Charusso, dkrupp, donat.nagy, mikhail.ramalho, a.sidorin, rnkovacs, szepet, whisperity.
Herald added a project: clang.
Harbormaster failed remote builds in B65978: Diff 281152!
Harbormaster returned this revision to the author for changes because remote builds failed.
steakhal requested review of this revision.
steakhal added a comment.
Manually force **request review**, to start a discussion about this.
Although I managed to implement this in a way to pass the tests, but the logic became somewhat messy, that's why I stick to this //dummy// patch.
I'm gonna clean that up and update the diff, if you think that such handing of memregions are valid.
Sorry for the `cfe-dev` spam, I did not know that I can manually //request review//.
Currently, if the analyzer evaluates an expression like `to - from`, it only computes reasonable answer if both are representing ElementRegions.
Formally, **for all** memory region `X` and **for all** SVal offset `Y`:
`&Element{SymRegion{X},Y,char} - &SymRegion{X}` => `Y`
The same for the symmetric version, but returning `-Y` instead.
I'm curious why don't we handle the case, when only one of the operands is an `ElementRegion` and the other is a plain `SymbolicRegion`.
IMO if the SuperMemoryRegion is the same, we can still return a reasonable answer.
In this patch, I suppose an extension to resolve this.
If this seems to be a good idea, I will:
- implement the symmetric version of the check
- add tests
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D84736
Files:
clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
Index: clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -1017,6 +1017,21 @@
}
}
+ // Try to get the Index as Nonloc, then cast to ArrayIndexTy.
+ // Otherwise return None.
+ const auto MaybeNonLocIndexOfElementRegion =
+ [this](const ElementRegion *ElemReg) -> Optional<NonLoc> {
+ SVal IndexVal = ElemReg->getIndex();
+ Optional<NonLoc> Index = IndexVal.getAs<NonLoc>();
+ if (!Index)
+ return llvm::None;
+ IndexVal = evalCastFromNonLoc(*Index, ArrayIndexTy);
+ Index = IndexVal.getAs<NonLoc>();
+ if (!Index)
+ return llvm::None;
+ return Index.getValue();
+ };
+
// Handle special cases for when both regions are element regions.
const ElementRegion *RightER = dyn_cast<ElementRegion>(RightMR);
const ElementRegion *LeftER = dyn_cast<ElementRegion>(LeftMR);
@@ -1027,31 +1042,32 @@
// give the correct answer.
if (LeftER->getSuperRegion() == RightER->getSuperRegion() &&
LeftER->getElementType() == RightER->getElementType()) {
- // Get the left index and cast it to the correct type.
- // If the index is unknown or undefined, bail out here.
- SVal LeftIndexVal = LeftER->getIndex();
- Optional<NonLoc> LeftIndex = LeftIndexVal.getAs<NonLoc>();
- if (!LeftIndex)
- return UnknownVal();
- LeftIndexVal = evalCastFromNonLoc(*LeftIndex, ArrayIndexTy);
- LeftIndex = LeftIndexVal.getAs<NonLoc>();
- if (!LeftIndex)
- return UnknownVal();
- // Do the same for the right index.
- SVal RightIndexVal = RightER->getIndex();
- Optional<NonLoc> RightIndex = RightIndexVal.getAs<NonLoc>();
- if (!RightIndex)
- return UnknownVal();
- RightIndexVal = evalCastFromNonLoc(*RightIndex, ArrayIndexTy);
- RightIndex = RightIndexVal.getAs<NonLoc>();
- if (!RightIndex)
+ Optional<NonLoc> LeftIndex = MaybeNonLocIndexOfElementRegion(LeftER);
+ Optional<NonLoc> RightIndex = MaybeNonLocIndexOfElementRegion(RightER);
+
+ if (!LeftIndex || !RightIndex)
return UnknownVal();
// Actually perform the operation.
// evalBinOpNN expects the two indexes to already be the right type.
return evalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy);
}
+ } else if (LeftER && isa<SymbolicRegion>(RightMR)) {
+ if (LeftER->getSuperRegion() != RightMR)
+ return UnknownVal();
+ if (Optional<NonLoc> LeftIndex = MaybeNonLocIndexOfElementRegion(LeftER))
+ return LeftIndex.getValue();
+ return UnknownVal();
+ } else if (RightER && isa<SymbolicRegion>(LeftMR)) {
+ if (RightER->getSuperRegion() != LeftMR)
+ return UnknownVal();
+ if (Optional<NonLoc> RightIndex =
+ MaybeNonLocIndexOfElementRegion(RightER))
+ llvm_unreachable(
+ "TODO: return the negated value of RightIndex - figure out how :D\n"
+ "Maybe a unary minus operator would do the job.");
+ return UnknownVal();
}
// Special handling of the FieldRegions, even with symbolic offsets.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D84736.281152.patch
Type: text/x-patch
Size: 3341 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200728/0fcbbf40/attachment.bin>
More information about the cfe-commits
mailing list