This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] Extend NoStoreFuncVisitor to recursively follow fields
ClosedPublic

Authored by george.karpenkov on Jul 26 2018, 7:19 PM.

Details

Summary

It's probably worth to refactor a machinery for finding a path to a particular region from a particular region into a common subroutine.

rdar://39701823

Diff Detail

Repository
rL LLVM

Event Timeline

george.karpenkov updated this revision to Diff 157824.
george.karpenkov edited the summary of this revision. (Show Details)
george.karpenkov updated this revision to Diff 157826.
george.karpenkov added inline comments.
clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
398 ↗(On Diff #157826)

@Szelethus the code below does pointer-chasing and tries to find a chain of regions from an input region to the region of interest.
Do you think it would make sense to extract in and share with your checker?

NoQ requested changes to this revision.Jul 30 2018, 4:13 PM

Looks great! Marking as "requested changes" as per repeated requests from the working class.

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
294–296 ↗(On Diff #158028)

This would need a rebase after an update to D49772.

326–331 ↗(On Diff #158028)

Hmm, shouldn't we also verify that the receiver is the super-region of the region of interest, like we do in other places?

350–351 ↗(On Diff #158028)

I think you should use my new function, Call->getAdjustedParameterIndex(I), that's added in D49715, because parameters and arguments aren't always in sync. Then you also don't have to check parameters explicitly.

390 ↗(On Diff #158028)

Maybe let's add a TODO to warn people that we're passing vectors around quadratically?

462 ↗(On Diff #158028)

Let's instead cast it to ImplicitParamDecl and check its kind, just to be sure.

598 ↗(On Diff #158028)

I'm not sure i understand this comment.

398 ↗(On Diff #157826)

+

This revision now requires changes to proceed.Jul 30 2018, 4:13 PM
george.karpenkov marked 4 inline comments as done.
NoQ requested changes to this revision.Jul 30 2018, 6:14 PM

Looks good, apart from waiting on D49715 for getAdjustedParameterIndex().

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
330–332 ↗(On Diff #158141)

Let's re-order the checks. The isSubRegionOf() check is cheaper.

This revision now requires changes to proceed.Jul 30 2018, 6:14 PM

Is something like this worth adding to the C++ test file?

struct HasRefToItself {
  HasRefToItself &Ref; // no infinite loop
  int &z;
  HasRefToItself(int &z) : Ref(*this), z(z) {}
};

Maybe a list-like struct that has a cycle?

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
398 ↗(On Diff #157826)

Whoo, thanks for tagging me! Sadly I have little knowledge about visitors so I can't add anything meaningful to the conversation just yet, but I really like what I'm seeing in this function. I'll definitely take a look how I could incorporate this into my checker, as pointer handling is kind of a mess there.

Is something like this worth adding to the C++ test file?

We limit the recursion depth to 1 for fields, so it won't dereference fields more than once. It could be still worthwhile to have this test to make sure this condition does not break.

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
390 ↗(On Diff #158028)

I'll add a note. It's not an issue if our vectors are of size <= 2, and for a bigger size we'll have other problems first.

462 ↗(On Diff #158028)

OK. Probably deserves a separate matcher.

398 ↗(On Diff #157826)

@Szelethus the fact that it's in the visitor is immaterial here, I'm just talking about the function findRegionOfInterestInRecord.
Basically, it tries to solve a (subset) of the problem of "whether there's a path from region A to region B".
The output should either be "no path" or a sequence of regions denoting a path.

In a broad sense, that's a breadth-first-search where possible operations are

  • Dereferencing the region
  • Looking for subregions
  • Going through the fields
  • Going through superclasses

That seems too expensive though, so here we only dereference fields twice.

george.karpenkov marked 2 inline comments as done.
george.karpenkov added inline comments.
clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
330–332 ↗(On Diff #158141)

it depends, but OK

350–351 ↗(On Diff #158028)

I don't understand the semantics if the optional is empty. What then?

NoQ added inline comments.Aug 1 2018, 5:29 PM
clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
350–351 ↗(On Diff #158028)

If the optional is empty, then the argument doesn't correspond to any parameter. For example, CXXOperatorCallExpr takes this-argument as an explicit argument, but CXXMethodDecl of a member operator doesn't take it as a parameter, but treats it as an implicit parameter instead, so no valid index into parameters() can be returned.

NoQ accepted this revision.Aug 1 2018, 5:32 PM

Looks good!

This revision is now accepted and ready to land.Aug 1 2018, 5:32 PM
This revision was automatically updated to reflect the committed changes.
NoQ added inline comments.Aug 2 2018, 3:13 PM
cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
354–356

Uhm! I realized that i was wrong about this one. You don't need the adjustment when iterating through CallEvent arguments; you only need it when iterating through CallExpr arguments, which are also conveniently shifted against each other.