This is an archive of the discontinued LLVM Phabricator instance.

[Analyzer] Track RValue expressions
ClosedPublic

Authored by martong on Mar 25 2021, 8:08 AM.

Details

Summary

It makes sense to track rvalue expressions in the case of special
concrete integer values. The most notable special value is zero (later
we may find other values). By tracking the origin of 0, we can provide a
better explanation for users e.g. in case of division by 0 warnings.
When the divisor is a product of a multiplication then now we can show
which operand (or both) was (were) zero and why.

Diff Detail

Event Timeline

martong created this revision.Mar 25 2021, 8:08 AM
martong requested review of this revision.Mar 25 2021, 8:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 25 2021, 8:08 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

From the first glance, everything is looking good! Thanks for addressing this!
But I still need to have a deeper look.

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
1932–1933

I think this should become an assertion and the caller should ensure that E is actually an r-value

1950

APSInt

I really like it. Looks good.
I'm letting someone else accept this as I've not really touched the trackExpression parts.

clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
119–124 ↗(On Diff #333309)

It is supposed to be called by the trackExpressionValue().
Why do we expose this function then?

martong updated this revision to Diff 333347.Mar 25 2021, 10:47 AM
  • Assert in the callee and check in the caller
  • Fix typo in comment
martong marked an inline comment as done.Mar 25 2021, 10:51 AM
martong added inline comments.
clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
119–124 ↗(On Diff #333309)

I was thinking about that maybe some Checkers could explicitly want to track RValues only. On the other hand, maybe it just complicates the public API. Anyway, I'd like to hear what other people say about this.

NoQ added a comment.Mar 25 2021, 1:54 PM

I think this is a good targeted fix for that problem we've discussed, demonstrated by tests.

clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
119–124 ↗(On Diff #333309)

I suggest keep it private until there's an actual use case. As of now literally nobody understands how these functions are even supposed to work so it's way too early to give API promises.

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
1945

SVal::isZeroConstant() please ^.^

martong updated this revision to Diff 333508.Mar 26 2021, 1:38 AM
martong marked 5 inline comments as done.
  • Use isZeroConstant()
  • Make trackRValueExpression private (static function)
  • Fix clang-tidy report: auto *BO ---> const auto *BO

Guys, thanks for the review! :)

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
1945

Yeah good catch, I wish I knew this before :)

Some minor logical issues inline.

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
1944–1945

There are only 3 multiplicative operators:

BINARY_OPERATION(Mul, "*")
BINARY_OPERATION(Div, "/")
BINARY_OPERATION(Rem, "%")

So, the opcode can never be BO_MulAssign later.
The comment for the else block is also inaccurate for the same reason.

martong updated this revision to Diff 333848.Mar 29 2021, 6:40 AM
  • Remove handling of assignment
martong marked an inline comment as done.Mar 29 2021, 6:43 AM
martong added inline comments.
clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
1944–1945

Yep, good catch! The reason why the assignment test case passed is that we already handle assignment operations in the FindLastStoreBRVisitor.

// If this is an assignment expression, we can track the value
// being assigned.
if (Optional<PostStmt> P = Succ->getLocationAs<PostStmt>())
  if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>())
    if (BO->isAssignmentOp())
      InitE = BO->getRHS();

So, I could just remove the handling of the assignment from the new function.

martong marked an inline comment as done.Mar 29 2021, 6:44 AM
steakhal added inline comments.Mar 30 2021, 1:44 AM
clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
1958–1959

Both divisions and modulo operations can flow here.

martong updated this revision to Diff 334093.Mar 30 2021, 3:12 AM
  • Update comment
martong marked an inline comment as done.Mar 30 2021, 3:12 AM
martong added inline comments.
clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
1958–1959

Ok, I updated the comment.

steakhal accepted this revision.Mar 30 2021, 3:50 AM

land it

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
1938

This note is not strictly for this patch.

At first, it wasn't clear to me why you call getSValAsScalarOrLoc().
That just returns unknown if the Region is not boundable. Unfortunately, the MemRegion::isBoundable() has no documentation. IMO all virtual call deserves documentation.

This revision is now accepted and ready to land.Mar 30 2021, 3:50 AM
This revision was automatically updated to reflect the committed changes.
martong marked an inline comment as done.