Hi all.
The follwing three files reproduce an error I've encountered while porting some code from gpc on Linux to gpc on OsX.
----------- file p1.pas -------- module p1;
export p1 = all;
const P = 155;
function Something() :boolean;
end;
function Something: boolean; begin Something := false; end;
end. ------------ file p2.pas --------- module p2;
export p2 = all;
const P = 155;
function SomethingElse :boolean;
end;
function SomethingElse: boolean; begin SomethingElse := false; end;
end. ----------- file testconst.pas ------- program test(input, output);
import p1;p2;
var a,b : boolean; c : integer;
begin a := Something; b := SomethingElse; c := P; writeln('test'); end.
---------------------------------------------------
If I try gpc --automake testconst.pas on my linux box it works fine. If I try the same command on my Mac I receive the following output:
p2.pas:5: error: redeclaration of `P' p1.pas:5: error: previous declaration
Please note that if you change both P and c to boolean type, everything works fine both on Linux and OsX
Precisely, on Linux I am running gpc 20041218 based on gcc-3.3.3. On the Mac I run GNU Pascal version 20041218, based on gcc-3.4.3, i.e. the one currently available on microbizz.
Any hint?
Thanks, Stefano
Stefano Carpin wrote:
Hi all.
The follwing three files reproduce an error I've encountered while porting some code from gpc on Linux to gpc on OsX.
----------- file p1.pas -------- module p1;
export p1 = all;
const P = 155;
function Something() :boolean;
end;
function Something: boolean; begin Something := false; end;
end. ------------ file p2.pas --------- module p2;
export p2 = all;
const P = 155;
function SomethingElse :boolean;
end;
function SomethingElse: boolean; begin SomethingElse := false; end;
end. ----------- file testconst.pas ------- program test(input, output);
import p1;p2;
var a,b : boolean; c : integer;
begin a := Something; b := SomethingElse; c := P; writeln('test'); end.
If I try gpc --automake testconst.pas on my linux box it works fine. If I try the same command on my Mac I receive the following output:
p2.pas:5: error: redeclaration of `P' p1.pas:5: error: previous declaration
Please note that if you change both P and c to boolean type, everything works fine both on Linux and OsX
Precisely, on Linux I am running gpc 20041218 based on gcc-3.3.3. On the Mac I run GNU Pascal version 20041218, based on gcc-3.4.3, i.e. the one currently available on microbizz.
Any hint?
The problem has nothing to do with Mac OSX. It appears in Mac OSX because patch to allow compiling with gcc-3.4.3 also contains qualified identifiers support.
Note that gpc-20041218 did almost no checking on import, for example it allowed you to have `p = 155' in p1 but `p = 156' in p2, which is wrong (EP requires imports to be unique). Your example is valid, but it was not clear if it is usefull. Exact rules deciding which of similar programs are valid are somewhat tricky. gpc-20050217 (and gpc-20041218 compiled with gcc-3.4.3) use simplified rules which go wrong in your case. gpc will accept your program when the full rules get implemented (pobably in the next version).
For extra background: normally Pascal allows only one definition at given level (you can redefine names inside routines). Import counts also as a definition. There is a special exception, which roughly speaking means that you can import "the same" thing from multiple modules. The tricky part is what "the same" means. Currently it is "coming from the same declaration". However we need to compare values of constants coming from two declarations. For integers like 155 it is easy, but in general gpc allows quite complicated constans...
It is probably best to define constants in one place (having different definitions for the same constant may easily introduce bugs). If you need to have consistent definitions in multiple modules, then you need to wait for future gpc versions. If you have two distinct constants which just happen to have the same name, then you need to tell in import statement which one do you want, like:
import p1;p2 only (SomethingElse);
or
import p1(p => p1_p); p2;
The first version takes from p2 only `SomethingElse', the second renames `p' coming from p1 to `p1_p'. You can also use qualified import to avoid conflicts.