I am working with gpc-20030507 (with gcc-3.2.3, i486-pc-mingw), and I have noted two changes in compiler behavior from gpc-20021128. I don't know whether these are bugs or intentionally revised features.
1. The "addr" function no longer observes the --no-typed-address command line switch. The GPC manual says:
--no-typed-address Make the result of the address operator an untyped pointer (same as {$T-}).
...and:
Addr returns the address of its argument. It is equivalent to the address operator....
...so I would expect that "addr" and "@" would behave the same. They did under gpc-20021128. However, this now fails to compile with "--no-typed-address":
program addrtest;
var i : integer; a, b : ^ byte;
begin a := @ i; { ok if --no-typed-address, fails otherwise } b := addr (i); { fails always, "incompatible pointer type" } end.
2. Using an interface-only module to declare routines in an exernal library no longer works. The importing program declares an external to "_init_<module-name>", but no entry point is provided by the module, so the program won't link. The GPC manual says:
To use a function written in another language, you need to provide an external declaration for it - either in the program, or in the interface part of a unit, or an interface module.
So I would think that the following would work:
[ifmod.pas]
module ifmod interface;
export ifmod = (proc);
procedure proc;
end.
[iftest.pas]
program ifbug;
import ifmod (proc);
begin proc end.
They both compile but fail during linking (presuming a library is supplied that declares "_Proc" as an entry point) with an undefined reference to "init_Ifmod". This worked in gpc-20021128 because "iftest.o" did not reference the "_init_Ifmod" entry point.
-- Dave
J. David Bryan wrote:
I am working with gpc-20030507 (with gcc-3.2.3, i486-pc-mingw), and I have noted two changes in compiler behavior from gpc-20021128. I don't know whether these are bugs or intentionally revised features.
The latter.
- The "addr" function no longer observes the --no-typed-address command
line switch. The GPC manual says:
--no-typed-address Make the result of the address operator an untyped pointer (same as {$T-}).
...and:
Addr returns the address of its argument. It is equivalent to the address operator....
...so I would expect that "addr" and "@" would behave the same. They did under gpc-20021128. However, this now fails to compile with "--no-typed-address":
program addrtest;
var i : integer; a, b : ^ byte;
begin a := @ i; { ok if --no-typed-address, fails otherwise } b := addr (i); { fails always, "incompatible pointer type" } end.
In BP, `Addr' is always untyped. I consider this a historical bug (because in older BP versions also `@' was untyped). So GPC does this only with `--borland-pascal'. Otherwise it's always typed (which I consides more sane -- if you want to convert the pointer, you can always use an explicit cast, rather than hiding the fact).
Only `@' now depends on `--typed-address', in GPC just like in BP.
I'll adjust the documentation.
- Using an interface-only module to declare routines in an exernal library
no longer works. The importing program declares an external to "_init_<module-name>", but no entry point is provided by the module, so the program won't link. The GPC manual says:
To use a function written in another language, you need to provide an external declaration for it - either in the program, or in the interface part of a unit, or an interface module.
Also here, I'll change the documentation. EP is clear on that an interface module requires an implementation.
Solution: Use a non-interface module (drop `interface' and add `end;' before `end.').
They both compile but fail during linking (presuming a library is supplied that declares "_Proc" as an entry point) with an undefined reference to "init_Ifmod". This worked in gpc-20021128 because "iftest.o" did not reference the "_init_Ifmod" entry point.
Which was a bug that caused some serious problems (e.g., strings in interface modules not being initialized).
Frank
On 10 Jul 2003 at 22:27, Frank Heckenbach wrote:
J. David Bryan wrote:
I don't know whether these are bugs or intentionally revised features.
The latter.
Noted, thanks.
EP is clear on that an interface module requires an implementation.
Yes, but must that implementation be an EP module? EP 6.13 section 2d suggests not, saying that interfacing to other languages might be provided by:
"The association of a module-heading with a construct in another language that the implementation has determined to be equivalent to a module-block."
That would seem to indicate that an interface-only EP module is legal if an appropriate implementation is provided elsewhere. That would provide for compiling and linking an EP program, an EP interface-only module, and a non- EP routine that provides the module-block (implementation). The introduction in the EP manual appears to support this concept:
"Modules provide a framework for implementation of libraries and non-Pascal program components."
Solution: Use a non-interface module (drop `interface' and add `end;' before `end.').
But changing to:
module ifmod;
export ifmod = (proc);
procedure proc;
end;
end.
...gives me:
ifmod.pas:7: unresolved forward declaration `proc'
GPC is looking for an implementation of "proc" in the module-block, which makes sense. So that means that I need to declare "proc" external as well.
I have re-read the thread "Modules without implementation" at:
http://www.gnu-pascal.de/crystal/gpc/en/thread8400.html
Gale Paeper suggests adopting the "implementation advice" in EP 6.1.5, i.e.:
"A processor may provide, as an extension, the interface-directive external, which is used to specify that the module-block corresponding to the module-heading containing the interface-directive is in some form other than an Extended Pascal module-block (e.g., it is implemented in some other language)."
Whereas you suggest the EP 6.1.4 mechanism:
"...I prefer to specify this on a per routine basis, because it's not generally optimal to have everything or nothing external...."
I take your point, except in the case where everything _is_ provided by an external module (e.g., interfacing to a non-Pascal library). In that case, it is tedious and error-prone to append "external" after each of perhaps dozens or hundreds of routines.
Which was a bug that caused some serious problems (e.g., strings in interface modules not being initialized).
An important consideration except in cases where the implementation is provided by an external source.
-- Dave
J. David Bryan wrote:
EP is clear on that an interface module requires an implementation.
Yes, but must that implementation be an EP module? EP 6.13 section 2d suggests not, saying that interfacing to other languages might be provided by:
"The association of a module-heading with a construct in another language that the implementation has determined to be equivalent to a module-block."
That would seem to indicate that an interface-only EP module is legal if an appropriate implementation is provided elsewhere.
It is just an informal ("NOTES") suggestion ("could be provided in one of the following ways") for "an extension", which to my understanding means that such a mechanism would be just as non-standard as any other.
...gives me:
ifmod.pas:7: unresolved forward declaration `proc'
GPC is looking for an implementation of "proc" in the module-block, which makes sense. So that means that I need to declare "proc" external as well.
If it's external, you must declare it `external'. That should always have been so, but GPC didn't strictly check it until the major changes in the area of `asmname', `external' etc. in 20030323.
I have re-read the thread "Modules without implementation" at:
http://www.gnu-pascal.de/crystal/gpc/en/thread8400.html
Gale Paeper suggests adopting the "implementation advice" in EP 6.1.5, i.e.:
"A processor may provide, as an extension, the interface-directive external, which is used to specify that the module-block corresponding to the module-heading containing the interface-directive is in some form other than an Extended Pascal module-block (e.g., it is implemented in some other language)."
Whereas you suggest the EP 6.1.4 mechanism:
"...I prefer to specify this on a per routine basis, because it's not generally optimal to have everything or nothing external...."
I take your point, except in the case where everything _is_ provided by an external module (e.g., interfacing to a non-Pascal library). In that case, it is tedious and error-prone to append "external" after each of perhaps dozens or hundreds of routines.
It can easily be automatized. Besides, if you want to declare external routines, you have to specify the linker name (aka asmname), anyway, and writing `attribute (name = 'foo')' vs. `external name 'foo'' isn't so much easier or harder.
When you (previously) wrote an interface-module without a corresponding implementation-module, you were kind of "cheating", since the interface claims that a Pascal implementation of the routines declared (without `external') would follow, whereas it didn't and was replaced (at link time) by a C (or whatever) implementation. Due to the bug that module initializers weren't called, this happened to work. In addition, you were apparently relying in C code on the default linker name of Pascal routines (first letter upper-case, rest lower-case) which is also a bad idea and will break at least when qualified identifiers are added.
Frank
On 12 Jul 2003 at 3:01, Frank Heckenbach wrote:
It is just an informal ("NOTES") suggestion...
Indeed.
...which to my understanding means that such a mechanism would be just as non-standard as any other.
Agreed, but the EP standard defines the meaning of "extension" and suggests several (e.g., "external" as an interface-directive), so my reading is that certain extension mechanisms would be preferred over others.
Besides, if you want to declare external routines, you have to specify the linker name (aka asmname), anyway, and writing `attribute (name = 'foo')' vs. `external name 'foo'' isn't so much easier or harder.
It isn't so much a matter of writing as of reading. A module declared with:
module ifmod external;
...clearly shows that everything contained in the module is supplied by an external entity, whereas:
module ifmod;
...with dozens or perhaps hundreds of "external" directives on individual procedures, variables, etc. makes it much harder to determine by inspection whether anything is supplied in the (Pascal) module implementation.
In addition, you were apparently relying in C code on the default linker name of Pascal routines (first letter upper-case, rest lower-case)....
Actually, I was supplying "asmname"s for each routine to obtain the proper linkage to the third-party library.
-- Dave
J. David Bryan wrote:
It isn't so much a matter of writing as of reading. A module declared with:
module ifmod external;
...clearly shows that everything contained in the module is supplied by an external entity,
... which, in my experience, is (or should be) rarely the case, since C routines have C-ish interfaces which often need wrappers to convert them to Pascal-ish form.
whereas:
module ifmod;
...with dozens or perhaps hundreds of "external" directives on individual procedures, variables, etc. makes it much harder to determine by inspection whether anything is supplied in the (Pascal) module implementation.
Why not by inspection of the module implementation? ;-)
Well, if you want to implement it, just go ahead. I won't spend my time on it since, as I said, I don't consider it too useful, and even somewhat bad in that it may encourage people to not write the Pascal wrappers so they can use the "simpler" external interface declaration, and so the C semantics will spread unnecessarily to the higher-level Pascal code. It's a matter of style sure, but experience shows that many people are lazy and will happily chose a worse solution if it just has some superficial advantage. (But as I said, if you want to implement it, I won't reject it. But I suggest you first research if there is any other compiler with such a feature, so that, in case there is, we'll at least be compatible if possible.)
Frank