views:

386

answers:

1

We're writing code inside the Linux kernel so, try as I might, I wasn't able to get PC-Lint/Flexelint working on Linux kernel code. Just too many built-in symbols etc. But that's a side issue.

We have any number of compilers, starting with gcc, but others also. Their warnings options have been getting stronger over time, to where they are pretty strong static analysis tools too.

Here is what I want to catch. Yes, I know it violates some things that are easy to catch in code review, such as "no magic numbers", and "beware of bit shifting", but that's only if you happen to look at that section of code. Anyway, here it is:

unsigned long long foo;
unsigned long bar;

[... lots of other code ...]

foo = ~(foo + (1<<bar));

Further UPDATED problem description -- even with bar limited to 16, still a problem. Clarifying, the problem is implicit int type of constant that, unplanned, makes the complex expression violate the rule that all calculations be carried out in the same size and signedness.

Problem: '1' is not long long, but, as a small-value constant, defaults to an int. Therefore even if bar's actual value never exceeds, say, 16, still the (1<<bar) expression will overflow and ruin the entire calculation.

Possibly correct solution: write 1ULL instead.

Is there a well-known compiler and compiler warning flag that will point out this (revised) problem?

+1  A: 

I am not sure what criteria you are thinking of to flag this construction as suspicious. There is clearly something wrong if the value of bar is as large as than the size (in bits) of an int, but usually the compiler wouldn't know that. From the point of view of a heuristic, bug-finding tool, having good patterns to separate likely bugs from normal constructions is key to avoiding too many false positives (which make users hate the tool and refuse to use it).

The Open Source tool in my URL flags logical shifts by a number larger than the size of the type, but it is primarily a verification tool for critical embedded software and expect a lot of work to appropriate it if you intend to use it on the Linux kernel with its linked structures and other difficulties.

Pascal Cuoq
I'll have a look at your website. I realize that by suggesting bar at 64, I misled. I changed it to 16. Even then there's a problem, that lint catches but I'm looking for gcc to catch. Problem isn't the too-large-shift, per se. It's the complex expression with, unintended, multiple types in it.
talkaboutquality