About preprocessing and include guards

G

gutmant

Say you have a file, a.h with an include guard.
If you include it twice and look at the preprocessed output, you see
there's no sign for the second inclusion.
However, if you include it twice - once from a relative path, and once
from an absolute one - you see that the second inclusion indeed occurs
(enters the file and leaves immediately due to the include guard).

Why does this happen (I have my speculations, but I want some
reassurance...), and is there any way to make it always act like in
the latter case?

Thanks,
- Tali
 
G

Gennaro Prota

Say you have a file, a.h with an include guard.
If you include it twice and look at the preprocessed output, you see
there's no sign for the second inclusion.
However, if you include it twice - once from a relative path, and once
from an absolute one - you see that the second inclusion indeed occurs
(enters the file and leaves immediately due to the include guard).

Why does this happen (I have my speculations, but I want some
reassurance...)

Because of the way your implementor decided to implement the whole
thing. Never try to deduce language rules by experimenting.
 
I

Ivan Vecerina

: Say you have a file, a.h with an include guard.
: If you include it twice and look at the preprocessed output, you see
: there's no sign for the second inclusion.
: However, if you include it twice - once from a relative path, and once
: from an absolute one - you see that the second inclusion indeed occurs
: (enters the file and leaves immediately due to the include guard).
:
: Why does this happen (I have my speculations, but I want some
: reassurance...), and is there any way to make it always act like in
: the latter case?

The latter case is the standard behavior ( = actually including
and parsing the whole file).

The former case is an allowed optimization, under the "as if" rule.
Some compilers detect files whose structure is:
...only comments or blank lines...
#ifndef SOME_KEYWORD
#define SOME_KEYWORD

#endif
...only comments or blank lines...
They keep trace of the path and keyword, and avoid reloading the
file at all if the keyword is already defined.

If the file contains C++ statements, or any non-comment / non-blanks
outside of the #ifndef...#endif block, this specific optimization
cannot be performed.
So you should not need to worry about it...

Ivan
 
G

Gennaro Prota

: Say you have a file, a.h with an include guard.
: If you include it twice and look at the preprocessed output, you see
: there's no sign for the second inclusion.
: However, if you include it twice - once from a relative path, and once
: from an absolute one - you see that the second inclusion indeed occurs
: (enters the file and leaves immediately due to the include guard).
:
: Why does this happen (I have my speculations, but I want some
: reassurance...), and is there any way to make it always act like in
: the latter case?

The latter case is the standard behavior ( = actually including
and parsing the whole file).

"Standard" in what sense.
The former case is an allowed optimization, under the "as if" rule.
Some compilers detect files whose structure is:
...only comments or blank lines...
#ifndef SOME_KEYWORD
#define SOME_KEYWORD

#endif
...only comments or blank lines...
They keep trace of the path and keyword, and avoid reloading the
file at all if the keyword is already defined.

If the file contains C++ statements, or any non-comment / non-blanks
outside of the #ifndef...#endif block, this specific optimization
cannot be performed.

Nope. EDG, for instance, documents to do the optimization even with

#pragma once
#ifndef A_H
#define A_H
...
#endif
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Say you have a file, a.h with an include guard.
If you include it twice and look at the preprocessed output, you see
there's no sign for the second inclusion.
However, if you include it twice - once from a relative path, and once
from an absolute one - you see that the second inclusion indeed occurs
(enters the file and leaves immediately due to the include guard).

Why does this happen (I have my speculations, but I want some
reassurance...), and is there any way to make it always act like in
the latter case?

Probably because you have a preprocessor smart enough not to include the
same file (as in path) twice, thus saving the time it takes to open the
file and pre-process it. And why would you want the latter behaviour
when the first is preferable?
 
I

Ivan Vecerina

: On Wed, 20 Jun 2007 14:26:28 +0200, Ivan Vecerina wrote:
:
: >: >: Say you have a file, a.h with an include guard.
: >: If you include it twice and look at the preprocessed output, you
see
: >: there's no sign for the second inclusion.
: >: However, if you include it twice - once from a relative path, and
once
: >: from an absolute one - you see that the second inclusion indeed
occurs
: >: (enters the file and leaves immediately due to the include guard).
: >:
: >: Why does this happen (I have my speculations, but I want some
: >: reassurance...), and is there any way to make it always act like in
: >: the latter case?
: >
: >The latter case is the standard behavior ( = actually including
: >and parsing the whole file).
:
: "Standard" in what sense.

As defined in the ANSII/ISO C++ standard.
For instance ISO/IEC 14482, See §2.1 = Phases of translation.

: >The former case is an allowed optimization, under the "as if" rule.
: >Some compilers detect files whose structure is:
: > ...only comments or blank lines...
: > #ifndef SOME_KEYWORD
: > #define SOME_KEYWORD
: >
: > #endif
: > ...only comments or blank lines...
: >They keep trace of the path and keyword, and avoid reloading the
: >file at all if the keyword is already defined.
: >
: >If the file contains C++ statements, or any non-comment / non-blanks
: >outside of the #ifndef...#endif block, this specific optimization
: >cannot be performed.
:
: Nope. EDG, for instance, documents to do the optimization even with
:
: #pragma once
: #ifndef A_H
: #define A_H
: ...
: #endif

#pragma once itself is a non-standard extension, implemented notably
by Microsoft's C++ compilers. As all #pragma directives, it should
be "ignored" by an implementation that does not understand it.
#pragma once being used in MSVC to request this exact same optimization
(not re-parsing the file if it is #included twice), it just makes
sense for EDG to support this extension in this way.
 
G

gutmant

Probably because you have a preprocessor smart enough not to include the
same file (as in path) twice, thus saving the time it takes to open the
file and pre-process it. And why would you want the latter behaviour
when the first is preferable?

First of all - thank you all for taking the time to respond.

Erik, obviously that is the preferable behavior when you're trying to
compile... I need to get some data from the preprocessed files, and
I'm currently deprived of that data due to the above optimization...
Ivan, if this is an "allowed optimization" - can I cancel it? Is there
a preprocessor that doesn't do that?

Thanks again to everyone!
- Tali
 
R

Roland Pibinger

Ivan, if this is an "allowed optimization" - can I cancel it? Is there
a preprocessor that doesn't do that?

Do you have include guards for the included file?
 
G

gutmant

Do you have include guards for the included file?

Roland - Yes, and I need them there, too.
Also, I forgot to mention we're talking about a huge amount of code. I
can't change the code, I can either change the preprocessor (currently
using g++) or use some g++ flag if exists (which I failed to find).
Thanks for taking the time to answer! :)
- Tali
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Roland - Yes, and I need them there, too.

If the data you need is inside these include guards then it does not
matter whether the file is parsed or not, the data will not be included
anyway. If it is not within the include guards but the file is not
parsed then you should report the bug to the gcc developers.
 
G

gutmant

If the data you need is inside these include guards then it does not
matter whether the file is parsed or not, the data will not be included
anyway. If it is not within the include guards but the file is not
parsed then you should report the bug to the gcc developers.

Erik,
It's not in the file at all - I just want to see all the included
files listed. It's not a bug, it's most certainly the intended
behavior of the preprocessor (optimized, of course), but I'd like to
turn that optimization off somehow.
Thanks again,
-Tali
 
M

Michael DOUBEZ

(e-mail address removed) a écrit :
Erik,
It's not in the file at all - I just want to see all the included
files listed. It's not a bug, it's most certainly the intended
behavior of the preprocessor (optimized, of course), but I'd like to
turn that optimization off somehow.
Thanks again,

If you use gcc, you can look at the -M flag which output all
dependencies from a source file (or -MM if you don't want system headers).

Note: this is OT here.

Michael
 
G

gutmant

(e-mail address removed) a écrit :





If you use gcc, you can look at the -M flag which output all
dependencies from a source file (or -MM if you don't want system headers).

Note: this is OT here.

Michael

Sweet! That's good to know!
I'm actually trying to build an inclusion tree, so it looks like it
won't help me too much, As I don't have the depth data...
It also skips the second time you include a file so... :/
But thanks a lot Michael! :)
 
G

Gennaro Prota

: >The latter case is the standard behavior ( = actually including
: >and parsing the whole file).
:
: "Standard" in what sense.

As defined in the ANSII/ISO C++ standard.
For instance ISO/IEC 14482, See §2.1 = Phases of translation.

I'd have thought that clause 16 played a role as well. Anyway, I think
you missed my point: there's always the as-if rule, which you
mentioned, and thus no requirement that the file contents actually
undergo all phases of translation again, as long as no difference is
detectable from observable behavior. This means that neither cases
violates the standard (as long as the optimization is done correctly).
: >The former case is an allowed optimization, under the "as if" rule.
Exactly.

: >Some compilers detect files whose structure is:
: > ...only comments or blank lines...
: > #ifndef SOME_KEYWORD
: > #define SOME_KEYWORD
: >
: > #endif
: > ...only comments or blank lines...
: >They keep trace of the path and keyword, and avoid reloading the
: >file at all if the keyword is already defined.
: >
: >If the file contains C++ statements, or any non-comment / non-blanks
: >outside of the #ifndef...#endif block, this specific optimization
: >cannot be performed.
:
: Nope. EDG, for instance, documents to do the optimization even with
:
: #pragma once
: #ifndef A_H
: #define A_H
: ...
: #endif

#pragma once itself is a non-standard extension, implemented notably
by Microsoft's C++ compilers.

Again, you missed my point. I said "for instance". There can be other
non-comment/non-blanks which do not preclude the specific
optimization. You simply cannot state that, in general, "If the file
contains C++ statements, or any non-comment / non-blanks outside of
the #ifndef...#endif block, this specific optimization cannot be
performed". That's not true.
 
J

James Kanze

On Jun 20, 5:24 pm, Michael DOUBEZ <[email protected]> wrote:
I'm actually trying to build an inclusion tree, so it looks like it
won't help me too much, As I don't have the depth data...
It also skips the second time you include a file so... :/

If the goal is to build an inclusion tree, the obvious solution
is to not use the compiler at all; parsing just the #include
statements isn't so awfully difficult.

If you really want the compiler to do part of the job, the
"obvious" solution is to construct a wrapper which does nothing
but include the file in question, and preprocess that. It won't
give you the full tree, but it will give you the information
about which files are included from file X, which you can use to
build the full tree.
 
I

Ivan Vecerina

: On Wed, 20 Jun 2007 14:44:55 +0200, Ivan Vecerina wrote:
....
: >: >The former case is an allowed optimization, under the "as if"
rule.
:
: Exactly.
:
: >: >Some compilers detect files whose structure is:
: >: > ...only comments or blank lines...
: >: > #ifndef SOME_KEYWORD
: >: > #define SOME_KEYWORD
: >: >
: >: > #endif
: >: > ...only comments or blank lines...
: >: >They keep trace of the path and keyword, and avoid reloading the
: >: >file at all if the keyword is already defined.
....
: Again, you missed my point. I said "for instance". There can be other
: non-comment/non-blanks which do not preclude the specific
: optimization. You simply cannot state that, in general, "If the file
: contains C++ statements, or any non-comment / non-blanks outside of
: the #ifndef...#endif block, this specific optimization cannot be
: performed". That's not true.

I mentioned the "as if" rule, then illustrated why the OP was
observing the behavior that he reported, and explained why he
did not need to worry about it in practice.

Was your point relevant in the scope of trying to assist the OP ?

plonk
--Ivan
 
I

Ivan Vecerina

I'm actually trying to build an inclusion tree, so it looks like
it won't help me too much, As I don't have the depth data...
It also skips the second time you include a file so... :/
But thanks a lot Michael! :)

If you haven't yet, give doxygen a try:
http://www.doxygen.org

It can build inclusion/dependency trees, and a number
of other things...


I hope this helps,
Ivan
 
G

gutmant

If you haven't yet, give doxygen a try:
http://www.doxygen.org

It can build inclusion/dependency trees, and a number
of other things...

I hope this helps,
Ivan
--http://ivan.vecerina.com/contact/?subject=NG_POST<- email contact form

Thanks Ivan, but sadly doxygen can't help me here. The problems of
adapting to an existing situation :)
Still would be happy if anyone knows how to "turn off" the
preprocessor optimization :)
Thanks to everyone!
- Tali
 
M

Michael DOUBEZ

James Kanze a écrit :
If the goal is to build an inclusion tree, the obvious solution
is to not use the compiler at all; parsing just the #include
statements isn't so awfully difficult.

A library like freetype2 uses defined for files to include. I guess at
least in this case the preprocessor would be needed.
If you really want the compiler to do part of the job, the
"obvious" solution is to construct a wrapper which does nothing
but include the file in question, and preprocess that. It won't
give you the full tree, but it will give you the information
about which files are included from file X, which you can use to
build the full tree.

IMHO it is the best solution. But there is still the problem of the
include path passed to the actual compiler.

Michael
 

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
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top