mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-05 16:08:01 +02:00
* rework syntax for cblocks: now a cblock directive is required
* additionally implicit calling conventions of cdecl or mwpascal now work as well * adjusted tests + added tests Note: the generator for packages/univint needs to be fixed, until then building on macOS will be broken git-svn-id: trunk@43684 -
This commit is contained in:
parent
c477816100
commit
8111e92e1f
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -14106,6 +14106,8 @@ tests/test/tblock1a.pp svneol=native#text/plain
|
|||||||
tests/test/tblock1c.pp svneol=native#text/plain
|
tests/test/tblock1c.pp svneol=native#text/plain
|
||||||
tests/test/tblock2.pp svneol=native#text/plain
|
tests/test/tblock2.pp svneol=native#text/plain
|
||||||
tests/test/tblock2a.pp svneol=native#text/plain
|
tests/test/tblock2a.pp svneol=native#text/plain
|
||||||
|
tests/test/tblock3a.pp svneol=native#text/pascal
|
||||||
|
tests/test/tblock3b.pp svneol=native#text/pascal
|
||||||
tests/test/tbopr.pp svneol=native#text/plain
|
tests/test/tbopr.pp svneol=native#text/plain
|
||||||
tests/test/tbrtlevt.pp svneol=native#text/plain
|
tests/test/tbrtlevt.pp svneol=native#text/plain
|
||||||
tests/test/tbsx1.pp svneol=native#text/plain
|
tests/test/tbsx1.pp svneol=native#text/plain
|
||||||
|
@ -1611,7 +1611,7 @@ parser_w_enumeration_out_of_range=03353_W_Enumeration symbols can only have valu
|
|||||||
%
|
%
|
||||||
# Type Checking
|
# Type Checking
|
||||||
#
|
#
|
||||||
# 04124 is the last used one
|
# 04126 is the last used one
|
||||||
#
|
#
|
||||||
% \section{Type checking errors}
|
% \section{Type checking errors}
|
||||||
% This section lists all errors that can occur when type checking is
|
% This section lists all errors that can occur when type checking is
|
||||||
@ -2047,6 +2047,10 @@ type_e_function_reference_kind=04123_E_Subroutine references cannot be declared
|
|||||||
type_e_seg_procvardef_wrong_memory_model=04124_E_Procedure variables in that memory model do not store segment information
|
type_e_seg_procvardef_wrong_memory_model=04124_E_Procedure variables in that memory model do not store segment information
|
||||||
type_w_empty_constant_range_set=04125_W_The first value of a set constructur range is greater then the second value, so the range describes an empty set.
|
type_w_empty_constant_range_set=04125_W_The first value of a set constructur range is greater then the second value, so the range describes an empty set.
|
||||||
% If a set is constructed like this: \var{s:=[9..7];]}, then an empty set is generated. As this is something normally not desired, the compiler warns about it.
|
% If a set is constructed like this: \var{s:=[9..7];]}, then an empty set is generated. As this is something normally not desired, the compiler warns about it.
|
||||||
|
type_e_cblock_callconv=04126_E_C block reference must use CDECL or MWPASCAL calling convention.
|
||||||
|
% When declaring a C block reference ensure that it uses either the \var{cdecl} or \var{mwpascal}
|
||||||
|
% calling convention either by adding the corresponding function directive or by using the
|
||||||
|
% \var{$Calling} compiler directive.
|
||||||
% \end{description}
|
% \end{description}
|
||||||
#
|
#
|
||||||
# Symtable
|
# Symtable
|
||||||
|
@ -1053,21 +1053,19 @@ implementation
|
|||||||
cgmessage(type_e_function_reference_kind)
|
cgmessage(type_e_function_reference_kind)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if (po_hascallingconvention in tprocvardef(hdef).procoptions) and
|
{ this message is only temporary; once Delphi style anonymous functions
|
||||||
(tprocvardef(hdef).proccalloption in [pocall_cdecl,pocall_mwpascal]) then
|
are supported, this check is no longer required }
|
||||||
begin
|
if not (po_is_block in tprocvardef(hdef).procoptions) then
|
||||||
include(tprocvardef(hdef).procoptions,po_is_block);
|
comment(v_error,'Function references are not yet supported, only C blocks (add "cblock;" at the end)');
|
||||||
{ can't check yet whether the parameter types
|
end;
|
||||||
are valid for a block, since some of them
|
|
||||||
may still be forwarddefs }
|
|
||||||
end
|
|
||||||
else
|
|
||||||
{ a regular anonymous function type: not yet supported }
|
|
||||||
{ the }
|
|
||||||
Comment(V_Error,'Function references are not yet supported, only C blocks (add "cdecl;" at the end)');
|
|
||||||
end
|
|
||||||
end;
|
end;
|
||||||
handle_calling_convention(tprocvardef(hdef),hcc_default_actions_intf);
|
handle_calling_convention(tprocvardef(hdef),hcc_default_actions_intf);
|
||||||
|
if po_is_function_ref in tprocvardef(hdef).procoptions then
|
||||||
|
begin
|
||||||
|
if (po_is_block in tprocvardef(hdef).procoptions) and
|
||||||
|
not (tprocvardef(hdef).proccalloption in [pocall_cdecl,pocall_mwpascal]) then
|
||||||
|
message(type_e_cblock_callconv);
|
||||||
|
end;
|
||||||
if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
|
if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
|
||||||
consume(_SEMICOLON);
|
consume(_SEMICOLON);
|
||||||
end;
|
end;
|
||||||
|
@ -2388,7 +2388,7 @@ type
|
|||||||
end;
|
end;
|
||||||
const
|
const
|
||||||
{Should contain the number of procedure directives we support.}
|
{Should contain the number of procedure directives we support.}
|
||||||
num_proc_directives=52;
|
num_proc_directives=53;
|
||||||
proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
|
proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
@ -2436,6 +2436,15 @@ const
|
|||||||
mutexclpocall : [];
|
mutexclpocall : [];
|
||||||
mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
|
mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
|
||||||
mutexclpo : [po_assembler,po_external]
|
mutexclpo : [po_assembler,po_external]
|
||||||
|
),(
|
||||||
|
idtok:_CBLOCK;
|
||||||
|
pd_flags : [pd_procvar];
|
||||||
|
handler : nil;
|
||||||
|
pocall : pocall_none;
|
||||||
|
pooption : [po_is_block];
|
||||||
|
mutexclpocall : [];
|
||||||
|
mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
|
||||||
|
mutexclpo : [po_assembler,po_external]
|
||||||
),(
|
),(
|
||||||
idtok:_CDECL;
|
idtok:_CDECL;
|
||||||
pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
|
pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
|
||||||
|
@ -170,6 +170,7 @@ type
|
|||||||
_WHILE,
|
_WHILE,
|
||||||
_WRITE,
|
_WRITE,
|
||||||
_ADDREF,
|
_ADDREF,
|
||||||
|
_CBLOCK,
|
||||||
_DISPID,
|
_DISPID,
|
||||||
_DIVIDE,
|
_DIVIDE,
|
||||||
_DOWNTO,
|
_DOWNTO,
|
||||||
@ -511,6 +512,7 @@ const
|
|||||||
(str:'WHILE' ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
|
(str:'WHILE' ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
|
||||||
(str:'WRITE' ;special:false;keyword:[m_none];op:NOTOKEN),
|
(str:'WRITE' ;special:false;keyword:[m_none];op:NOTOKEN),
|
||||||
(str:'ADDREF' ;special:false;keyword:[m_none];op:NOTOKEN),
|
(str:'ADDREF' ;special:false;keyword:[m_none];op:NOTOKEN),
|
||||||
|
(str:'CBLOCK' ;special:false;keyword:[m_none];op:NOTOKEN),
|
||||||
(str:'DISPID' ;special:false;keyword:[m_none];op:NOTOKEN),
|
(str:'DISPID' ;special:false;keyword:[m_none];op:NOTOKEN),
|
||||||
(str:'DIVIDE' ;special:false;keyword:[m_none];op:NOTOKEN), { delphi operator name }
|
(str:'DIVIDE' ;special:false;keyword:[m_none];op:NOTOKEN), { delphi operator name }
|
||||||
(str:'DOWNTO' ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
|
(str:'DOWNTO' ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{$modeswitch cblocks}
|
{$modeswitch cblocks}
|
||||||
|
|
||||||
type
|
type
|
||||||
tblock = reference to procedure; cdecl;
|
tblock = reference to procedure; cdecl; cblock;
|
||||||
|
|
||||||
procedure test(b: tblock);
|
procedure test(b: tblock);
|
||||||
begin
|
begin
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
{$modeswitch cblocks}
|
{$modeswitch cblocks}
|
||||||
|
|
||||||
type
|
type
|
||||||
tblock = reference to procedure; cdecl;
|
tblock = reference to procedure; cdecl; cblock;
|
||||||
|
|
||||||
procedure test(b: tblock);
|
procedure test(b: tblock);
|
||||||
begin
|
begin
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{$modeswitch cblocks}
|
{$modeswitch cblocks}
|
||||||
|
|
||||||
type
|
type
|
||||||
tblock = reference to function(l: longint): longint; cdecl;
|
tblock = reference to function(l: longint): longint; cdecl; cblock;
|
||||||
|
|
||||||
function test(b: tblock; l: longint): longint;
|
function test(b: tblock; l: longint): longint;
|
||||||
begin
|
begin
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
{$modeswitch cblocks}
|
{$modeswitch cblocks}
|
||||||
|
|
||||||
type
|
type
|
||||||
tblock = reference to procedure(j: longint); cdecl;
|
tblock = reference to procedure(j: longint); cdecl; cblock;
|
||||||
|
|
||||||
tc = class
|
tc = class
|
||||||
i: longint;
|
i: longint;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
{$modeswitch cblocks}
|
{$modeswitch cblocks}
|
||||||
|
|
||||||
type
|
type
|
||||||
tblock = reference to procedure(j: longint); cdecl;
|
tblock = reference to procedure(j: longint); cdecl; cblock;
|
||||||
|
|
||||||
tc = class
|
tc = class
|
||||||
i: longint;
|
i: longint;
|
||||||
|
75
tests/test/tblock3a.pp
Normal file
75
tests/test/tblock3a.pp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
{ %target=darwin,iphonesim}
|
||||||
|
{ %skipcpu=powerpc,powerpc64 }
|
||||||
|
|
||||||
|
program tblock3a;
|
||||||
|
|
||||||
|
{$mode objfpc}
|
||||||
|
{$modeswitch cblocks}
|
||||||
|
|
||||||
|
type
|
||||||
|
{$calling cdecl}
|
||||||
|
tblock1 = reference to procedure(j: longint); cblock;
|
||||||
|
|
||||||
|
{$calling mwpascal}
|
||||||
|
tblock2 = reference to procedure(j : longint); cblock;
|
||||||
|
|
||||||
|
tc = class
|
||||||
|
i: longint;
|
||||||
|
procedure callme(j: longint);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
b1: tblock1;
|
||||||
|
b2: tblock2;
|
||||||
|
c: tc;
|
||||||
|
|
||||||
|
procedure tc.callme(j: longint);
|
||||||
|
const
|
||||||
|
invocationcount: longint = 0;
|
||||||
|
begin
|
||||||
|
writeln('self: ',hexstr(pointer(self)),', i: ',i,', j: ',j);
|
||||||
|
if self<>c then
|
||||||
|
halt(1);
|
||||||
|
if i<>12345 then
|
||||||
|
halt(2);
|
||||||
|
case invocationcount of
|
||||||
|
0:
|
||||||
|
if j<>1 then
|
||||||
|
halt(3);
|
||||||
|
1, 2:
|
||||||
|
if j<>2 then
|
||||||
|
halt(4);
|
||||||
|
3:
|
||||||
|
if j<>3 then
|
||||||
|
halt(5);
|
||||||
|
4, 5:
|
||||||
|
if j<>4 then
|
||||||
|
halt(6);
|
||||||
|
end;
|
||||||
|
inc(invocationcount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure test1(b: tblock1);
|
||||||
|
begin
|
||||||
|
b1(2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure test2(b: tblock2);
|
||||||
|
begin
|
||||||
|
b2(4);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
c:=tc.create;
|
||||||
|
c.i:=12345;
|
||||||
|
b1:=@c.callme;
|
||||||
|
b1(1);
|
||||||
|
test1(@c.callme);
|
||||||
|
test1(b1);
|
||||||
|
b2:=@c.callme;
|
||||||
|
b2(3);
|
||||||
|
test2(@c.callme);
|
||||||
|
test2(b2);
|
||||||
|
end.
|
||||||
|
|
16
tests/test/tblock3b.pp
Normal file
16
tests/test/tblock3b.pp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{ %FAIL }
|
||||||
|
{ %target=darwin,iphonesim}
|
||||||
|
{ %skipcpu=powerpc,powerpc64 }
|
||||||
|
|
||||||
|
program tblock3b;
|
||||||
|
|
||||||
|
{$mode objfpc}
|
||||||
|
{$modeswitch cblocks}
|
||||||
|
|
||||||
|
type
|
||||||
|
{$calling stdcall}
|
||||||
|
tblock = reference to procedure; cblock;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user