This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] assume bitwise arithmetic axioms
ClosedPublic

Authored by george.karpenkov on Nov 6 2017, 4:23 PM.

Details

Summary

Patches the solver to assume that bitwise OR of an unsigned value with a constant always produces a value larger-or-equal than the constant, and bitwise AND with a constant always produces a value less-or-equal than the constant.

This patch is especially useful in the context of using bitwise arithmetic for error code encoding: the analyzer would be able to state that the error code produced using a bitwise OR is non-zero.

I have considered in very great detail the option of adding the matching code in ExprEngine / SimpleSValBuilder and have found it unfeasible: ideally we would like to pattern match in a great variety of situations: whether the created bitwise value is stored, compared, or added to other values.
Considering all those cases would have led to a very large amount of code duplication.

Diff Detail

Repository
rL LLVM

Event Timeline

xazax.hun accepted this revision.Nov 7 2017, 4:45 AM

This looks like a great addition! Apart from some nits, LGTM.

lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
487 ↗(On Diff #121825)

Comments should be sentences (start with capital letter and have a period).

498 ↗(On Diff #121825)

This new line is redundant. Also, there are way more new lines in this method than there usually are in LLVM.

This revision is now accepted and ready to land.Nov 7 2017, 4:45 AM
NoQ accepted this revision.Nov 7 2017, 6:04 AM

Yep, nice and clean~

lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
520 ↗(On Diff #121825)

That's more and more "special case"s, i guess we'd have to make them legal. The getRange() function is not only a simple wrapper around State->get<>(), but it is also the single source of truth regarding constraints that can be assumed about the values by simply looking at the values, without exploring the program state. I think this should be reflected in the comments.

test/Analysis/constant-folding.c
92 ↗(On Diff #121825)

Can we still assume that b | 1 is non-zero? Maybe FIXME here?

dcoughlin edited edge metadata.Nov 8 2017, 10:47 AM

I believe your motivating examples used errno_t, which is a signed type.

I'm fine with assuming a two's complement value representation for signed integers, which would make Artem's suggestion work. That assumption definitely deserves a comment, though.

Handle non-zero case, more tests cases, cleaner code.

This looks good to me. It is very clean! But please add a comment in the places where you are assuming a two's complement value representation for signed integers.

dcoughlin accepted this revision.Nov 9 2017, 10:54 AM
This revision was automatically updated to reflect the committed changes.