For practical example, suppose ModuleA
have some type varying on conditional compilation:
unit ModuleA;
interface
type
{ explicit character width }
PASTR = type PAnsiChar;
PWSTR = type PWideChar;
{ imlicit character width }
PTSTR = {$IFDEF UNICODE}PWSTR{$ELSE}PASTR{$ENDIF};
{ ... }
And now the set of functions in ModuleB
is depending on the type declared in ModuleA
:
unit ModuleB;
{ ... }
implementation
uses ModuleA;
{ explicit }
function FuncA(Arg: PASTR): Integer;
begin
{ do something with 1 byte char }
end;
function FuncW(Arg: PWSTR): Integer;
begin
{ do something with 2 byte char }
end;
{ implicit - will compiler safeguard against mismatching UNICODE define? }
function Func(Arg: PTSTR): Integer;
begin
{ map to explicit one }
Result := {$IFDEF UNICODE}FuncW(Arg){$ELSE}FuncA(Arg){$ENDIF};
end;
Now, suppose ModuleA
has been compiled with UNICODE
symbol defined and DCU file has been generated. And then ModuleB
has been compiled using DCU information only without UNICODE
symbol (or vice versa case - ModuleA.dcu
generated as ANSI, and then there is an attempt to use it in Unicode ModuleB
).
Will Delphi compiler always fail when compiling a module with such conditional-based type mismatch? With type
keyword and without it? Is there any version specific behaviour?
As a bonus: I'm interested in the same for Free Pascal.
The compiler will fail to compile the program in that scenario. Both in Delphi and FPC.
One way to think about it is to expand the conditional code. Once written that way it becomes much clearer what the compiler will do. And this is the right mental model because that is how the compiler processes conditional code. It simply does not see the code that is in conditional branches that are not active.
Consider these two units:
unit Unit1;
// expanded with UNICODE defined
interface
type
PASTR = type PAnsiChar;
PWSTR = type PWideChar;
PTSTR = PWSTR;
implementation
end.
unit Unit2;
// expanded with UNICODE undefined
interface
implementation
uses
Unit1;
function FuncA(Arg: PASTR): Integer;
begin
end;
function FuncW(Arg: PWSTR): Integer;
begin
end;
function Func(Arg: PTSTR): Integer;
begin
Result := FuncA(Arg);
end;
end.
The definition of PTSTR
is found in Unit1
and it is an alias to PWSTR
. Hence the call to FuncA
will not compile.
The use of type
to make distinct types changes nothing either, because PAnsiChar
and PWideChar
are already incompatible.