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

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

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

498

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
528

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

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.