>Hi
>> I was wondering if there already exists a tool to do the following:
>> 1) Given a C/C++ source file, determine if the list of includes in the
>> source file are all actually required (basically to determine if the
>> source is including "obsolete" headers)
>from the manuals of gcc:
> -M [ -MG ]
> Tell the preprocessor to output a rule suitable for
> make describing the dependencies of each object
> file. For each source file, the preprocessor out-
> puts one make-rule whose target is the object file
> name for that source file and whose dependencies
> are all the files `#include'd in it. This rule may
> be a single line or may be continued with `\'-new-
> line if it is long. The list of rules is printed
> on standard output instead of the preprocessed C
> program.
This will generate a list of headers that the file does use, but doesn't
distinguish between headers that are actually used, and ones which aren't
needed at all. (I actually use the -M stuff in my makefile to auto
-generate dependancy files....)
Quote:>> 2) Also in the same source, determine if a header included in the
>> original source file is also included previously (presumably through a
>> third header file)
>This is commonly overcome by include guards. Multiply included files are
>so common, for example the C library headers, that there is no chance
>besides include guards anyway. IMO it is best to not know what is
>included by other headers, because I would consider this an
>implementation detail of this file. If I know it, I will rely on it and
>will get trapped later when the other header is changed.
I actually wasn't thinking/worried about multiple inclusions (doing the
include guard thing in my header files is a very deeply ingrained habit
by now).
Quote:>Checking for superfluous includes involves parsing the code to some
>degree, so this would be something to include into the compiler, but
>which might also yield a lot of work in the compiler to include the
>source to every symbol parsed. IMO it is unlikely that anybody able to
>do it needs it as well.
Yep... it would be a pain to parse the file...
Quote:>> I guess the only purpose of this tool would be to help maintain code
>> "cleanliness" (no extra includes...)
>> Comments?
>There are no extra includes in well designed code. You insert includes
>when you need them. You can't rely on includes included by those you
>include. I've never seen documentation of libraries where it's said that
>you can rely on this. In most cases it is said only what you have to
>include to get certain services in the code you write. This is common
>sense, if you do other things, it is likely that you confuse other
>people. You can't rely purely on the code you see, because most often
>there is nothing said within it you can rely on over the times. So you
>even cannot write tools doing this job automatically, without having
>incorrect behaviour in some cases.
I only agree with the statement: "There are no extra includes in well
designed code", if you add "when originally written.". It is a fact of
life that programs need to be maintained. It then becomes more difficult
to determine when an include is no longer needed. (If I remove all
references to symbol X from the source, do I still need header.h ?)
Quote:>I don't want to look through some levels of headers until I have found
>what I want to use. E.g. If the docs tell me to include file poiuz1 to
>use struct mnbv3 and I want to use functions using mnbv3 declared in
>header poiuz67, I'll include both, although poiuz67 would have sufficed
>now. If I want to use struct mnbv3 it means I access fields of that
>struct which must not be true if you are exclusively working with it
>through functions.
>If you have a strong feeling that there are unnecessary includes in your
>files, than it's at best called laziness, but there is the fact that
>some unconscious things might have happened to your code which has been
>bad all times.
>Programmers tend to be lazy at times... I've done some programming, too.
BTW: Programming is my job (I get paid to play! :) ). And programmers
tend to be lazy almost all of the time :) And in C++, being lazy is a
good thing (read Scott Meyers sometime... Effective C++, More Effective
C++) :)
Quote:>And extra includes have been along the least problems I have thought
>about. A much bigger nuisance are those include-everything.h files. This
>is good for the laziest programmers you can think of. Have everything
>available everywhere and go. There a lot more unconscious things happen
I can argue the include-everything.h point, but only in certain instances
(and I don't really want to start an argument, just discussing a
potentially useful tool) In general, I completely agree... lots of .h
files.
Quote:>than with some extra includes. If I see a C file not including stdio.h,
>then I assume that there is no printf in it, or not including stdlib.h,
>then there is no malloc in it. This is important information at
>(debugging) times. With those all.h headers, I just know that everything
>can happen everywhere.
I also want to know that if I am including stdio.h, that the source _is_
using printf/scanf, or if I include pthread.h that the source _is_ using
pthreads calls.
I will grant you that detecting header files that are included directly
as well as implicitly may not be truly handy. However this does lead to
the exact opposite thought. What about detecting header files that you
are using symbols from that are only included implicitly, but not
directly?
Quote:>I hope that I convinced you that those little includes at the beginning
>of your files are worth some conscious treatment, their occurence as
>well as their absence. It can't be done automatically and it shouldn't.
I'm not saying that the tool should automatically remove them, only to
advise you that header such-and-such is not used at all, and that this
-other-header is implicitly included.
The idea I had for the tool is to help in managing the software project
in such a way that the source code helps document itself. As we both
agree, programmers tend to be lazy... and since when do lazy people
properly comment their code? (I'm guilty on this one) :)
So... to revise the "specifications":
1) Given a C/C++ source file, determine if the list of includes in the
source file are all actually required (basically to determine if the
source is including "obsolete" headers)
2) Also in the same source, determine if a header included through
another header should be included on it's own (to rephrase, all symbols
referenced by the source should all be in directly included headers).
Note that these should be advisory statements, not modifications to the
source.