[cfe-dev] GRExprEngine and complexe
Ted Kremenek
kremenek at apple.com
Thu Jun 19 11:24:24 PDT 2008
On Jun 19, 2008, at 7:44 AM, Jean-Daniel Dupas wrote:
> I'm trying to do some static code analysis. Usually, my code uses
> tgmath.h to don't have to bother with all the maths fonctions
> variants.
> The problem is that some tgmaths fonctions have complex number
> support, and even if I do not use complex numbers directly, some
> complex operator may appears in my code.
>
> #include <tgmath.h>
>
> int main(int argc, char **argv) {
> sin(M_PI_2 - .8);
> return 0;
> }
>
> expand to
>
> int main(int argc, char **argv) {
> __builtin_choose_expr
> (__builtin_classify_type(1.57079632679489661923132169163975144 - .8)
> == 9,
> __builtin_choose_expr
> (__builtin_types_compatible_p
> (__typeof__(__real__(1.57079632679489661923132169163975144 - .8)),
> long double), csinl(1.57079632679489661923132169163975144 - .8),
> __builtin_choose_expr
> ((__builtin_types_compatible_p
> (__typeof__(__real__(1.57079632679489661923132169163975144 - .8)),
> double) ||
> __builtin_classify_type
> (__real__(1.57079632679489661923132169163975144 - .8)) == 1), (csin)
> (1.57079632679489661923132169163975144 - .8),
> csinf(1.57079632679489661923132169163975144 - .8))),
> __builtin_choose_expr
> (__builtin_types_compatible_p
> (__typeof__(1.57079632679489661923132169163975144 - .8), long
> double), sinl(1.57079632679489661923132169163975144 - .8),
> __builtin_choose_expr
> ((__builtin_types_compatible_p
> (__typeof__(1.57079632679489661923132169163975144 - .8), double) ||
> __builtin_classify_type(1.57079632679489661923132169163975144 - .8)
> == 1), (sin)(1.57079632679489661923132169163975144 - .8),
> sinf(1.57079632679489661923132169163975144 - .8))));
> return 0;
> }
>
> which contains some "__real__" operators.
>
> The problem is in GRExprEngine::VisitUnaryOperator(). There is no
> case for UnaryOperator::Real and UnaryOperator::Imag. So when a
> Real operator is reached, the
>
> assert (U->isIncrementDecrementOp()); is false.
>
> What should be done to fix this ?
Hi Jean-Daniel,
I've added some initial support for __real__ and __imag__ in
GRExprEngine:
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20080616/006179.html
This patch does two things:
1) The assertion you mentioned doesn't fire anymore.
2) We correctly reason about applying __real__ and __imag__ to non-
complex types:
__real__ x -> x
__imag__x -> 0
3) For complex types, the expression evaluates to Unknown. The next
step is to implement an RValue object that represents a Complex type,
and then implement so more transfer function logic.
Aside from implementing more logic for complex types (which largely
reduces to just reasoning about tuples of values), I think a larger
issue is that we don't really do any reasoning about floats right
now. This isn't an inherit limitation in the analyzer; it's just not
been done.
We've focused purely on integers right now because they are so
fundamental to reason about most branch conditions. Even the
analyzer's reasoning about integers right now is very much in the
early stages; all the analyzer reasons about is integer constants, and
not integer ranges. We on implementing integer range tracking, and
also plan on integrating more bit-level reason about integer values as
well (e.g., the values of some bits are known and others are not).
For floating point (real numbers), different static analyses have
taken different approaches. Some analyses like to reason about them
as arbitrary real numbers, while others try to reason about their
actual implementation on a machine (i.e., floats and doubles have
finite precision). GRExprEngine is being designed to defer such
choices to the plug-in transfer function object (i.e., the subclass of
GRTransferFunc) that is used for clients to implement "analysis-
specific" logic. This gives different clients to implement the level
of precision that they need for a particular task. Many clients won't
care about floating-point values, so it actual buys them scalability
to not reason about them at all (i.e., simply treating floats as
"Unknown").
Over the next couple of weeks I will be putting some significant
effort into cleaning up some of the core pieces of the analyzer, but I
honestly probably won't implement any specific support for reasoning
about floating-point values any time soon since that would have little
applicability for the problems I'm focusing on using static analysis.
I will probably shore up some of the support for complex types,
however, but only to the point that any specific reason about floats
will get reduced to method calls to the GRTransferFunc object (where
the default implementation will return "Unknown" for most complex
operations).
If you are interested in implementing some support for floating-point
values, the place to start would be to implement a subclass of
GRTransferFuncs (or a subclass of GRSimpleVals) that implements
transfer function logic for floats; e.g. implement support for add,
subtract, etc. More of the "assumption" logic (which implements
reasoning about ">", "==", etc.) will also get put into
GRTransferFuncs, so basically all the symbolic reasoning you would
want to do about floats could also be plug-in logic that doesn't have
to go directly into GRExprEngine. The purpose of GRExprEngine is to
reason about the details of the C syntax (as well as reason about
memory), and reduce the myriad of ways you can do the same thing in C
to a smaller set of operations that the plug-in transfer function
logic can deal with.
Ted
More information about the cfe-dev
mailing list