[m-dev.] for review: automatic header file inclusion guards.
Fergus Henderson
fjh at cs.mu.OZ.AU
Sun Jan 28 16:54:21 AEDT 2001
On 28-Jan-2001, Tyson Dowd <trd at cs.mu.OZ.AU> wrote:
> On 26-Jan-2001, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> > > Anyway, I don't want to waste time pushing this change past people who
> > > don't want it. The other way to do this is to hash the contents of the
> > > foreign_decl string -- so I will write some code to do this instead.
> >
> > That doesn't sound like a good idea either. To avoid hash collisions,
> > you'd need a cryptographically secure hash function, and that might be
> > expensive to compute. Furthermore, it's not the right semantics,
> > since if the user writes the same `foreign_decl' twice, it should get
> > included in their program twice, but what you propose would only
> > include it once.
>
> You say "if the use writes the same `foreign_decl' twice, it should get
> included in their program twice".
>
> But with the current implementation a single foreign_decl can be
> included any number of times (by #including and .opt file propogation).
> The number of times it is included in the program has no relationship
> with the number of foreign_decl pragmas.
Well, that's precisely what we're talking about changing.
> If you meant "included in the same scope twice",
I meant that each foreign_decl should be included in the program
exactly once, and that the appropriate mechanism should be used
to import that declaration into scopes that use it.
For C, import means `#include', so C foreign_decls will get
#included into more than one translation unit.
> then for C code this is
> not useful at all. In C, the same declarations given twice
> can only mean redeclaring exactly the same things, or giving a duplicate
> declaration error message (I think typedefs do this). Neither of these
> leads any further expressiveness.
That's not completely true, because of #ifdef and other preprocessor
tricks.
#ifndef COUNT
#define COUNT 1
#elif COUNT == 1
#undef COUNT
#define COUNT 2
#elif COUNT == 2
#undef COUNT
#define COUNT 3
/* ... */
#endif
That's probably not terribly useful in practice.
But there are some other more realistic cases.
For example, consider
:- pragma c_header_code("#define NDEBUG").
:- pragma c_header_code("#include <assert.h>").
:- pragma c_header_code("inline void foo(void) { assert(0); }").
:- pragma c_header_code("#undef NDEBUG").
:- pragma c_header_code("#include <assert.h>").
:- pragma c_header_code("inline void bar(void) { assert(0); }").
Also it is possible for users to include non-standard C extensions
which have side effects. For example, some C implementations
have extensions such as
#pragma warnings on // enable warnings
#pragma warnings off // disable warnings
#pragma warnings push // save the current warning setting
#pragma warnings pop // restore the previous warning setting
which can be used in header files. These have side effects, and so
the number of times that they are included is important.
> This is all a bit dicey, because we haven't really defined the meaning
> of foreign_decl.
Indeed! It's not clear whether the example above with assert()
should be supported.
However, unless there is a good reason not to support it,
I think we should.
> But I think it should be defined along the lines of
> "The declarations will be visible to any foreign_code in
> this module".
> It should *not* be defined as
> "The declarations will be pasted into the text of the program
> once for each foreign_decl pragma".
Why not?
Or, phrasing it more precisely:
The foreign declarations will be pasted into the text of the
program once for each foreign_decl pragma, in the same order
that they occured in the Mercury module, in an appropriate
place for publically visible declarations (e.g. for C they go
in a header file), and these declarations will be imported in
the appropriate manner for each language (e.g. using #include
for C) into each place that contains foreign code that was
defined in the same module as the foreign_decl pragma.
> If you want to get this, then you should use foreign_code, which should
> have semantics such as:
> "Each foreign code fragment will be compiled and included in the
> program".
> (this implies that multiple foreign code fragments will be compiled and
> included multiple times).
But that doesn't work for declarations which need to be visible to
other foreign code fragments.
> The cryptographically secure hash function is md5.
> I don't think it is expensive enough to be worried about (about 0.5
> seconds to do 13Mb of text), 0.15 seconds to do all the 765 .m files in
> the tests module).
OK.
> > I think a better approach, at least for the MLDS back-end, would be to
> > ensure that each foreign_decl gets written to exactly one header file,
> > namely the one corresponding to the module that defined it. Other C
> > files which might need those declarations should #include that header
> > file, rather than containing a copy of the foreign_decl. In other words
> > the MLDS back-end should discard foreign_decls read from `.opt' files,
> > and just make sure sure that it #includes all the necessary headers.
>
> This is reasonable too. But it means you cannot put foreign_code from
> another module into your .opt or .trans_opt file, because the
> foreign_code doesn't have a context attached to it, so you cannot tell
> where you are supposed to include the .h file from. I don't think we
> do this sort of optimization at the moment, but it sounds like one we
> should do someday.
Well, foreign_code from other modules definitely shouldn't get included
in `.opt' files, since each `.opt' file should only contain stuff from
its own module. For `.trans_opt' files it would make sense, but we
could easily record the source module with such declarations in
`.trans_opt' files.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
| of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list