automatically remove unused #includes from C source?

W

Walter Bright

Walter said:
Still, it is true that in the case of multiple source files that
together have 1500 #include, that you would not need to do pow(2,1500)
application tests, if you are using a compiler that supports
independant compilation and later linking. If you do have independant
compilation, then within each source file it is a 2^N process
to find all the #include combinations that will compile, but most of
the combinations will not. Only the versions that will compile need
to go into the pool for experimental linkage; linkage experiments
would be the product of the number of eligable compilations for each
source. Only the linkages that survived would need to go on for testing.
The number of cases that wil make it to testing is not possible to
estimate without statistical information about the probability that any
given #include might turn out to be unneeded.

You don't need to do linking or testing if you start with a known good
object file, and then remove #include's, compile, and do a bit compare
of the resulting object file.
 
W

Walter Roberson

Walter Bright said:
You don't need to do linking or testing if you start with a known good
object file, and then remove #include's, compile, and do a bit compare
of the resulting object file.

Right, after stripping out symbol tables and debug information and
timestamps and anything else that can cause the object file to differ
for identical generated code.

Which is what I'd said before, but to which Roland said was
"overdone" on the basis that you have to test your code after code
changes. So this subthread has been exploring the feasility of
his proposal to *not* use the "did it generate the same code"
approach and instead use the "does the final executable test out the
same" approach.
 
W

Walter Roberson

Then, analyze it to make sure you don't delete the #include of "seems_unused.h" in this:
#ifdef DEFINED_WITH_MINUS_D
-- so that next week, when somebody does gcc -DDEFINED_WITH_MINUS_D, the code still builds.


True -- and perhaps more difficult is the situation where there is
an environmental test such as checking the OS. If there is, for example,

#ifdef _solaris
#include <sys/some_solaris_only_include.h>
#endif

then unless one asserts _solaris then as far as the proposed automated
tester is concerned, the #include is "unused"... and if one -does-
assert _solaris then unless one has set up a strange and wonderful
cross-compilation environment, <sys/some_solaris_only_include.h>
probably doesn't exist locally so you won't be able to test whether
it is -really- needed for Solaris ...
 
K

Kenny McCormack

Right, after stripping out symbol tables and debug information and
timestamps and anything else that can cause the object file to differ
for identical generated code.

Trying to compare object files is just asking for non-determinancy.

What occurred to me, upon reading this thread originally, was that you
could probably make it work by compiling to assembler (-S option) and
then comparing the assembly files. That should get you pretty close.

Yet, now that I think about it, maybe all you have to do is run it
through the preprocessor (-E option). That *might* be good enough.
 
G

Gordon Burditt

Right, after stripping out symbol tables and debug information and
Trying to compare object files is just asking for non-determinancy.

I believe OSF/1 put a timestamp in every object file, so consecutive
compilations of the same source files always mismatched.
What occurred to me, upon reading this thread originally, was that you
could probably make it work by compiling to assembler (-S option) and
then comparing the assembly files. That should get you pretty close.
Maybe.

Yet, now that I think about it, maybe all you have to do is run it
through the preprocessor (-E option). That *might* be good enough.

I doubt it. The preprocessor will show unnecessary structure definitions,
unnecessary typedefs, and unnecessary function declarations. Also,
preprocessors tend to insert a lot of blank lines and stuff made from
implicit #line directives containing info from where in the source the
code came from.

Oh, and if you have unnecessary global variable declarations in
your unnecessary include file, they might show up in the assembly
file.

Incidentally, just what is an UNNECESSARY include file? There are
a variety of types of preprocessor symbols which may require special
handling:

- Environment testing symbols: things like __FreeBSD__ which are
used to test things about the environment it's going to be compiled/run
on. Alternative environments which might define or undefine these
symbols aren't available to examine. Or maybe there's a configuration
file with alternate versions that might be used on Windows, Linux,
MacOS, MS-DOS, etc.

- Program configuration symbols: Symbols that may be enabled by
build procedures (e.g. compiler command line) to make different
versions of the program: the debug version, the release version,
the corporate version, etc.

- NDEBUG. This is referenced by the assert() macro somehow and is
intended to be defined or undefined to build a different version
of the program.
 
P

Paul Connolly

CBFalconer said:
Does what work? Interpret too. There is a reason for quotes in
usenet articles.

Firstly I feel I must say that I like most of what you write in this group -
eminent sense.

Sorry to be so inarticulate - I was drunk - typically Irish - thought there
was a thread and you might cotton on (-;

A more specific (but less general) question is:
if in my foo.c file I #undef all definitions in header xyz.h then will
PC-Lint be able to detect that xyz.h need not be included ?
(this should be not construed as my approval of #undef - I believe in one
true definition and no muddying of the water - typically Catholic)
 
C

CBFalconer

Paul said:
.... snip ...

A more specific (but less general) question is:
if in my foo.c file I #undef all definitions in header xyz.h then
will PC-Lint be able to detect that xyz.h need not be included ?
(this should be not construed as my approval of #undef - I believe
in one true definition and no muddying of the water - typically
Catholic)

No, because there may be many necessary things left. I can
immediately think of prototypes, typedefs, externs, struct
definitions, not to mention the things that should not normally be
included in header files anyhow.
 
P

Paul Connolly

CBFalconer said:
No, because there may be many necessary things left. I can
immediately think of prototypes, typedefs, externs, struct
definitions, not to mention the things that should not normally be
included in header files anyhow.

This answers a different question to the one I asked.
If all (the all here is all-important) the definitions in xyz.h were
#undef-ed in foo.c (where xyz.h is included) then will PC-Lint be able to
detect that xyz.h need not be included in foo.c?
 
C

CBFalconer

Paul said:
This answers a different question to the one I asked.
If all (the all here is all-important) the definitions in xyz.h were
#undef-ed in foo.c (where xyz.h is included) then will PC-Lint be able to
detect that xyz.h need not be included in foo.c?

You can't undef everything. For example, a prototype. You can do
an xref of both the files and see if there is anything in common.
 
P

Paul Connolly

CBFalconer said:
You can't undef everything. For example, a prototype. You can do
an xref of both the files and see if there is anything in common.

This answer assumes that xyz.h has a form that is not indicated by the
question.

You can #undef everything in xyz.h if everything in xyz.h is #undefable
(tautology) - it is not mandatory that xyz.h contains something that in not
#undefable - my question was a conditional (if) on all the definitions in
xyz.h being #undefed - so xyz.h must be in that class of headers in which
all the definitions can be #undefed - there exist many headers that satisfy
that condition.

Strictly, (as you obviously know from your fine erudition in this forum)
prototypes are declarations not definitions. My question was about
definitions - I was rather vaguely assuming thet foo.c didn't refer to any
functions prototyped in in xyz.h - I thought the behaviour of PC-Lint wrt
referring to functions prototyped in the header had already been
established - I was wanting to extend that knowledge to understanding how
PC-Lint dealt with #undef in this particular case (I do want to know more
generally as well, but since you thought this was too broad a question to
ask, I just asked a specific question - hoping it might give me some
indication of what PC-Lint is able to do with code that has #undefs)

So here is my question again, but refined for what I thought was the
already-understood behaviour of PC-Lint wrt to prototypes:
If all (the all here is all-important) the definitions in xyz.h were
#undef-ed in foo.c (where xyz.h is included)
-- the new bit ------
and foo.c does not refer to any function prototyped in in xyz.h
----------------------
then will PC-Lint be able to
detect that xyz.h need not be included in foo.c?

The Jesuits would still see three flaws in my question and, since it might
amuse the readers of this forum, and I'm feeling Jesuitical, I'll tell you
two (-;

1. PC-Lint might be able to "detect" (your sloppy usage eejit Connolly) the
header need not be included - surely the point is what PC-Lint "reports" -
it might know, but not tell you.

2. The wording "need not be included" (your sloppy usage eejit Connolly) is
problematic for many - take as an example (just an example - there are many
more cases) abc.c with header abc.h that declares only the prototypes of
functions in abc.c, where the functions in abc.c are decalared in an order
such that no function refers to any function later in the text of the file
abc.c, and the declarations in abc.h agree with the definitions in abc.c,
then abc.h "need not be included" in abc.c - but many would argue that the
inclusion of abc.h in abc.c is "desirable", to keep the declarations
consistent with the definitions, in case the definition of the function
changes in the future.

3. An exercise for the reader.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,078
Messages
2,570,570
Members
47,204
Latest member
MalorieSte

Latest Threads

Top