This is an archive of the discontinued LLVM Phabricator instance.

Append CXXDefaultInitExpr's wrapped expression to the CFG when visiting a constructor initializer
ClosedPublic

Authored by epertoso on Dec 10 2013, 3:06 AM.

Diff Detail

Event Timeline

+cfe-commits

This doesn't actually help the analyzer yet: the init expression will be evaluated, but then the result will be thrown away and the old constant-evaluation mechanism will be used instead (see `ExprEngine::Visit`). I'm okay with you not worrying about this for now.

I do approve of the comment change, though.

lib/StaticAnalyzer/Core/BugReporter.cpp
251–261 ↗(On Diff #6000)

Usually we do this using ParentMap so that it's a linear search. We'd have to start adding the children of the CXXDefaultInitExpr to the ParentMap, though.

282–294 ↗(On Diff #6000)

This definitely needs testing. The whole point of this section is to make Xcode arrows prettier, so without a test case that actually includes a plist it's kind of useless.

If you have Xcode, you can test the new arrows by overriding the analyzer binary with the not-so-secret setting CLANG_ANALYZER_EXEC. If not, don't worry about the arrows for now; I'll get to them soon.

epertoso updated this revision to Unknown Object (????).Dec 11 2013, 8:27 AM
epertoso added inline comments.Dec 11 2013, 8:32 AM
lib/StaticAnalyzer/Core/BugReporter.cpp
251–261 ↗(On Diff #6000)

We don't actually need to know a statement's parent, I used a llvm::DenseSet instead. Unlike the ParentMap, it can be cleared.

282–294 ↗(On Diff #6000)

test/Analysis/edges-new.mm is actually a plist based test and without changes to this section it was failing (a CXXDefaultInitExpr may now include the field initializer, so it may spawn more than a PathDiagnosticControlFlowPiece).

I modified it a little bit (inserting a conditional operator in edges-new.mm at line 580) to make sure that there's no arrow pointing to (or starting from) the actual init expression.

jordan_rose added inline comments.Dec 11 2013, 11:08 AM
lib/StaticAnalyzer/Core/BugReporter.cpp
251–261 ↗(On Diff #6000)

I'm not sure why this is an improvement. You don't even get to short-circuit here, and you rebuild the set every time a path piece goes through this default init expr. What if the same constructor is called several times in the course of analyzing a top-level function?

282–294 ↗(On Diff #6000)

What I mean is that we need some positive tests here, such as tests where an error happens within the default expr. If you change a plist test without the plist output changing, you're very likely not testing anything new.

epertoso updated this revision to Unknown Object (????).Dec 13 2013, 6:36 AM
epertoso added inline comments.Dec 13 2013, 7:08 AM
lib/StaticAnalyzer/Core/BugReporter.cpp
251–261 ↗(On Diff #6000)

I'm using the ParentMap returned by AnalysisDeclContext::getParentMap() now. I think it makes more sense.
Do you see any problem with that?

282–294 ↗(On Diff #6000)

I added a null-pointer dereference at line 594 in edges-new.mm. This dereference happens in the default initializer expression when the value of another variable is set in the constructor.

The static analyzer now correctly detects the null-pointer dereference on that line. I'm still not 100% happy because, in the presence of multiple constructors, it's not immediately clear which one of them leads to the warning, but at least it won't go unnoticed.

There were indeed edges to the in-class initializer: I'm not sure what the correct behaviour should be in this regard. I tried to be conservative and the current patch prevents them from appearing.

Ah, thanks! But hm...that's not a very good path. We should definitely be allowing edges within the initializer (so we can see that the reason we choose the null pointer path is because a != 1.

If you don't want to deal with this right now, you can just add another configuration option to the CFG and have the analyzer currently not include these nodes. I'll take it back out once we've got the analyzer properly handling this as well.

Hi,
sorry for my late reply.

Regarding to events appearing in an in-class initializer expression, we have now two simple approaches: to add an option for the CFG builder (as you suggested), or to let the code remove all the edges excluding those appearing within the expression wrapped by the CXXDefaultInitExpr.

Currently (at least until r199843), those events will not be reported (either in Xcode or in the command line). The first approach preserves this behaviour.
{F24874} (screenshot: http://llvm-reviews.chandlerc.com/file/data/lqyk5vypoxtfxvvzbj6m/PHID-FILE-3fxx2h44c3u33vhpjvtg/).

With the second approach, the output is ambiguous in the presence of multiple constructors.
{F24876} (screenshot: http://llvm-reviews.chandlerc.com/file/data/43y6wcdmgsstwxsoo7aq/PHID-FILE-wwyqyn2u2pfnot4f3gue/)

I still prefer to see that warning. If anything more complex than the second approach is required, I'd prefer to keep it separate from this patch and follow the first one. Any suggestions?

Yeah, I'm not yet happy with the second approach. Notice how there are still no edges for the in-class initializer of Foo, even though that's clearly an important part of the path that leads to the null dereference. I don't want to block the main part of your patch (improving -Wuninitialized), so let's go with the option for now, and then do it right after.

epertoso updated this revision to Unknown Object (????).Jan 30 2014, 9:48 AM

OK, this just became simpler.

This is fine but it doesn't turn it on for anybody. Unless Richard has any objections, I think it's fine to turn this on for -Wuninitialized, just not for the analyzer. It looks like one good place to do this is in AnalysisManager, which is only used by the analyzer.

lib/Analysis/CFG.cpp
1098–1100

I would do this using nested ifs but otherwise this looks good.

epertoso updated this revision to Unknown Object (????).Feb 6 2014, 7:33 AM
epertoso added inline comments.
lib/Analysis/CFG.cpp
1098–1100

Done.

jordan_rose accepted this revision.Feb 13 2014, 9:21 AM

This looks good to me. Do you have commit access, or do you need one of us to commit it for you?

No, I don't have commit access.

Although the tests are passing, I'd still like to clarify the
unreachable code warnings:

The code in Richard's example doesn't generate a warning. Should it?

I could also try to spend another couple of days to see how the
unreachable code warnings are generated and make sure we're not doing
it when we shouldn't.

epertoso updated this revision to Diff 26969.Jun 2 2015, 7:23 AM
epertoso edited edge metadata.
epertoso removed rL LLVM as the repository for this revision.

Updated.

epertoso closed this revision.Jun 3 2015, 3:16 AM