[PATCH] D77802: [analyzer] Improved RangeSet::Negate support of unsigned ranges
Denys Petrov via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 17 02:40:33 PDT 2020
ASDenysPetrov marked 9 inline comments as done.
ASDenysPetrov added a comment.
@baloghadamsoftware
> However, please still extend the current tests
I've looked for some appropriate tests to extend, but haven't found. What would you advise to use instead of mine?
@steakhal
Thanks for the comments.
================
Comment at: clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp:217
+
+ const llvm::APSInt sampleValue = getMinValue();
+ const bool isUnsigned = sampleValue.isUnsigned();
----------------
steakhal wrote:
> Should we take it as `const ref` to prevent copying?
getMinValue returns APSInt by value, so it wouldn't make sense.
================
Comment at: clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp:572-573
if (const RangeSet *negV = State->get<ConstraintRange>(negSym)) {
- // Unsigned range set cannot be negated, unless it is [0, 0].
- if ((negV->getConcreteValue() &&
- (*negV->getConcreteValue() == 0)) ||
+ if (T->isUnsignedIntegerOrEnumerationType() ||
T->isSignedIntegerOrEnumerationType())
return negV;
----------------
steakhal wrote:
> Couldn't we simplify the disjunction to single `T->isEnumerationType()` or to something similar?
I've looked for similar single function, but there is no appropriate one. I decided not to add a new one to make patch more focused.
================
Comment at: clang/test/Analysis/constraint_manager_negate_difference.c:114-118
+void negated_unsigned_range(unsigned x, unsigned y) {
+ clang_analyzer_eval(x - y != 0); // expected-warning{{FALSE}} expected-warning{{TRUE}}
+ clang_analyzer_eval(y - x != 0); // expected-warning{{FALSE}} expected-warning{{TRUE}}
+ clang_analyzer_eval(x - y != 0); // expected-warning{{FALSE}} expected-warning{{TRUE}}
+}
----------------
steakhal wrote:
> What does this test case demonstrate? Could you elaborate on that?
> Why do you evaluate the `x - y != 0` here twice?
>Why do you evaluate the x - y != 0 here twice?
This is the root line which assertion occured on.
I'll add some comments.
================
Comment at: clang/unittests/StaticAnalyzer/RangeSetTest.cpp:23
+template <typename T> struct TestCase {
+ RangeSet original;
+ RangeSet expected;
----------------
steakhal wrote:
> According to the [LLVM coding style](https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly) we should use UpperCamelCase for variable names for new code.
>
> Note that the Analyzer Core was written in a different style, we should follow that there instead (at least IMO).
Here is a discussion [[ https://llvm.org/docs/Proposals/VariableNames.html | VariableNames]] I was guide. Seems like we can use camelBack for new code. Am I right? Also RangeSetTest.cpp already uses mixed naming as you can see.
================
Comment at: clang/unittests/StaticAnalyzer/RangeSetTest.cpp:27-28
+ TestCase(BasicValueFactory &BVF, RangeSet::Factory &F,
+ const std::initializer_list<T> &originalList,
+ const std::initializer_list<T> &expectedList)
+ : original(createRangeSetFromList(BVF, F, originalList)),
----------------
steakhal wrote:
> AFAIK since `std::initializer_list` is just two pointers we should take it by value.
I'm not sure about //should//, since initializer_list is a container and it'd be consistent if we handle it like any other compound object despite its implementation (IMO). But I can change it if you wish.
================
Comment at: clang/unittests/StaticAnalyzer/RangeSetTest.cpp:51
+ // init block
+ DiagnosticsEngine Diag{new DiagnosticIDs, new DiagnosticOptions};
+ FileSystemOptions FileSystemOpts;
----------------
steakhal wrote:
> Generally, `new expressions` are a code smell. We should use something like an `std::make_unique` to prevent memory leaks on exceptions.
> Though, I'm not sure if there is a similar function for `llvm::IntrusiveRefCntPtr<T>`s.
I'll make it more safe.
================
Comment at: clang/unittests/StaticAnalyzer/RangeSetTest.cpp:66
+ template <typename T> void checkNegate() {
+ using type = T;
+
----------------
steakhal wrote:
> To be honest, I'm not sure if `type` is more descriptive than `T`.
It is useful for debug purposes, for instance you can change it to `using type = int;` to verify something. It also untie from template argument list and make the code more flexible.
================
Comment at: clang/unittests/StaticAnalyzer/RangeSetTest.cpp:68
+
+ // use next values of the range {MIN, A, B, MID, C, D, MAX}
+
----------------
steakhal wrote:
> AFAIK full sentences are required for comments.
> https://llvm.org/docs/CodingStandards.html#commenting
I'll correct it.
================
Comment at: clang/unittests/StaticAnalyzer/RangeSetTest.cpp:113-120
+ // c.original.print(llvm::dbgs());
+ // llvm::dbgs() << " => ";
+ // c.expected.print(llvm::dbgs());
+ // llvm::dbgs() << " => ";
+ // negatedFromOriginal.print(llvm::dbgs());
+ // llvm::dbgs() << " => ";
+ // negatedBackward.print(llvm::dbgs());
----------------
steakhal wrote:
> Should we keep this?
I'm not sure, but I'd better keep it, because it is useful for debugging.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D77802/new/
https://reviews.llvm.org/D77802
More information about the cfe-commits
mailing list