| So... suppose I had:
|
| // file "a.h":
| #pragma pack
| struct A { /* members */ };
|
| Suppose that, without the pragma, sizeof(A) is 32, and with the
| pragma, sizeof(A) is 24.
|
| I think a user could reasonably expect that, when one replaces:
|
| #include "a.h"
|
| ... with:
|
| import a;
|
| ... where module a contains the exact same two lines of code above
| (plus an export thingy)...
|
| ... sizeof(A) is 24 when evaluated in the module that imports a.
|
| (I.e., the user assumes that an instance of sizeof(A) (in the
| including/importing code) does not change when migrating from
| "#include" to "import".)
|
| Agreed?
No.
"resoanably expects" depends on what story we tell users. If we tell
them that a module is just a glorified preprocessed file, then yeah I
can see how that can happen. But, the stories (e.g. Daveed's paper,
various presentations at committee meetings) suggest something
completely different: one where the processed form of a module is closer
to set of elaborations (fully type checked declarations) than sequence
of tokens to be reparsed over and over again.
In that story, I find it unreasonable expectation and quite counter
productive to expect the "pragma pack" should leak to the next module.
For a consistent story, we need a few things:
(a) what properties to expect from modules,
(b) how a module can be used, etc.
(c) how modules interact with classic compilation models
then we flesh out the rules to meet those expectations.
| Would you be ok with a future standard that permits a conforming
| implementation to behave that way?
At this point, I will answer "no": we are introducing a disruptive
technology and any non-portability of this magnitude (which affects both
users and implementations) ought to have its benefits clearly spelled
out and weighted against other alternatives.
| > If that is the case, are you suggesting that every module be
| > retranslated every time it is imported before of possible attributes
| > effects leaking into its import?
|
| No.
But, what you suggested earlier pretty much requires that, and you are
saying as much below:
| Basically, whenever the internally-genreated command switches to the
| front end change in a way that the implementation decides is
| significant, we should expect new object code and a new binary module
| file.
|
| And if a vendor decides that a pragma in source code needs to have the
| effect of changing that sub-invocation, and if those sub-invocations
| for the same module differ at any two points in the program, then we
| may want that to be regarded as an ODR violation.
Please explain *why* we need this uncertainty about the boundaries of
CPP directives. The examples you've given so far, suggest additional
work to preserve just the problems we have today with source file
inclusion model.
|
| Richard, have you seen any counter-examples to that while implementing modules?
|
| > What are we gaining compared to the current source file inclusion model?
|
| Um... "good stuff".
What are they?
| (speed, macro isolation, much, much shorter TUs, tools enabled by
| knowledge of the index of names that the compiler needs to make things
| fast)
How? You stated earlier:
# My understanding is that in Clang's implementation, there is a
# completely separate invocation of the front end for each import
# statement, so unless you put something in its execution environment to
# tell it, "pack the first struct", it will be as if #pragma pack was
# not there.
which pretty much supports the design point that even Clang's implementation
you are talking about does pragma isolation.
| > | So, if in 16.6 we were to insert wording to the effect of:
| > |
| > | "If a pragma appears before or after an import-statement, the
| > | effect of the pragma on the translation of the imported module is
| > | implementation-defined. Likewise, if a pragma appears within an
| > | imported module, the effect of the pragma on the translation of
| > | the module that imports the imported module is
| > | implementation-defined. "
| > |
| > | ... would that settle it?
| >
| > No. :-)
|
| Ok...
|
| <snip>
| > How about #line or #file directives?
|
| I don't know; what about #line?
It is a directive that changes the state of the CPP processor.
| Each module has its own separate translation unit (separate from the
| TU of any other module, including any importing module).
Define "each module has its own separate translation unit".
| So there is a separate preprocessing TU for each module (i.e.,
| different preprocessor outputs--probably to be implemented as one ".i"
| file for each file indicated by an import-statement).
|
| Where's the problem?
What is "separate preprocessing TU for each module"?
The only reasonable interpretation I can see is that effects of CPP
directives are ignored outside of module boundaries.
| > I believe we should consider CPP directives as whole instead of making lists.
|
| Ok, I'm curious to see where this goes...
|
| And if we can help to prevent implementors from doing stupid things at
| the intersection of pragmas and "import", that would be good...
The question isn't as much as preventing implementors from doing stupid
things than preventing ourselves from writing sloppy and possibly stupid
spec. Implementors will implement a spec; I would like to see us give
more thinking to these points.
| But if we never get to the point of talking about specific directives
| (including specific pragmas like "pack"), then I don't know where
| you're going with this.
I think "pragma directives" is specific enough for now. If we are
unable to say something coherent at that level and work out the
implications, then it is unlikely that we are going to produce a useful
spec for modules. Surely, we don't want the spec to be just a
documentation of the implementation du jour.
-- Gaby