Page 1 of 1

VAR [nil] for tagged structural parameters

Posted: Sat Jan 15, 2022 1:56 pm
by Zorko
It is now possible to declare the following parameter:

Code: Select all

MODULE Win; IMPORT SYSTEM;

PROCEDURE Proc (VAR [nil] lpModuleName: ARRAY OF CHAR);
END Proc;

BEGIN
  Proc(NIL)
END Win.
But this makes no sense, since ARRAY is not an untagged pointer, it is a tagged structure with length storage. The same about RECORDs.

How it works, or rather, does not work:

Image

The error is really caught inside DevOPC, and that's very good, but it's the wrong level. It should be caught at the moment of declaration in DevOPP.FormalParameters procedure. The suggested fix:

Image

The result of its work:

Image

Re: VAR [nil] for tagged structural parameters

Posted: Sat Jan 15, 2022 9:48 pm
by Zorko
Refinement of corrections (we need to additionally check the tagging of a structure):

Code: Select all

		ELSIF (sys # 0) & ((typ.comp = Record) OR (typ.comp = DynArr)) & ~typ.untagged THEN err(142)

Re: VAR [nil] for tagged structural parameters

Posted: Sat Jan 15, 2022 10:03 pm
by Zorko
After this fix, I found one entry in the module WinApi:

Code: Select all

PROCEDURE [stdcall] SetDIBColorTable* (p0: HDC; p1: INTEGER; p2: INTEGER; VAR [nil] p3: ARRAY OF RGBQUAD): INTEGER;
Where RGBQUAD is an untagged record, but p3 is an open tagged array with the length passed to the procedure inside.

For array as a VAR parameter, passed does not actually one value, but two: the array address and its length. Can you tell exactly what will be passed as length if you pass NIL here?

Code: Select all

SetDIBColorTable(0, 1, 2, NIL);
To avoid such an undefined behavior, I propose to redeclare it this way:

Code: Select all

PROCEDURE [stdcall] SetDIBColorTable* (p0: HDC; p1: INTEGER; p2: INTEGER; p3: POINTER TO ARRAY [untagged] OF RGBQUAD): INTEGER;
So, my fix has already helped find one problem and a potential source of errors.

Re: VAR [nil] for tagged structural parameters

Posted: Thu Jan 20, 2022 2:29 pm
by adimetrius
Moving the check up to the front-end of the compiler sounds like a good idea to me.

SetDIBColorTable is definitely a mistake:

PROCEDURE SetDIBColorTable (p0: WinApi.HDC; p1, p2: INTEGER; VAR [nil] p3: ARRAY OF WinApi.RGBQUAD): INTEGER;
UINT SetDIBColorTable(
[in] HDC hdc,
[in] UINT iStart,
[in] UINT cEntries,
[in] const RGBQUAD *prgbq
);
It expects 3 parameters, but BlackBox will pass it four. It's declaration needs to be fixed in MODULE WinApi as follows:
PROCEDURE SetDIBColorTable (p0: WinApi.HDC; p1, p2: INTEGER; IN [nil] p3: ARRAY [untagged] OF WinApi.RGBQUAD): INTEGER;