mirror of
https://gitlab.com/freepascal.org/fpc/pas2js.git
synced 2025-08-14 17:09:03 +02:00
fcl-passrc: check class intf impl proc type modifiers match
This commit is contained in:
parent
f9b7f1dbb2
commit
94cee0dc39
@ -1710,7 +1710,8 @@ type
|
|||||||
function CreateClassIntfMap(El: TPasClassType; Index: integer): TPasClassIntfMap;
|
function CreateClassIntfMap(El: TPasClassType; Index: integer): TPasClassIntfMap;
|
||||||
procedure CheckConditionExpr(El: TPasExpr; const ResolvedEl: TPasResolverResult); virtual;
|
procedure CheckConditionExpr(El: TPasExpr; const ResolvedEl: TPasResolverResult); virtual;
|
||||||
procedure CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure;
|
procedure CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure;
|
||||||
IsOverride: boolean);
|
IsOverride: boolean // override or class intf implementation
|
||||||
|
);
|
||||||
procedure CheckPointerCycle(El: TPasPointerType);
|
procedure CheckPointerCycle(El: TPasPointerType);
|
||||||
procedure CheckGenericTemplateTypes(El: TPasGenericType); virtual;
|
procedure CheckGenericTemplateTypes(El: TPasGenericType); virtual;
|
||||||
procedure ComputeUnaryNot(El: TUnaryExpr; var ResolvedEl: TPasResolverResult;
|
procedure ComputeUnaryNot(El: TUnaryExpr; var ResolvedEl: TPasResolverResult;
|
||||||
@ -6453,6 +6454,10 @@ begin
|
|||||||
RaiseMsg(20180322143202,nNoMatchingImplForIntfMethodXFound,
|
RaiseMsg(20180322143202,nNoMatchingImplForIntfMethodXFound,
|
||||||
sNoMatchingImplForIntfMethodXFound,
|
sNoMatchingImplForIntfMethodXFound,
|
||||||
[GetProcTypeDescription(IntfProc.ProcType,[prptdUseName,prptdAddPaths,prptdResolveSimpleAlias])],El); // ToDo: jump to interface list
|
[GetProcTypeDescription(IntfProc.ProcType,[prptdUseName,prptdAddPaths,prptdResolveSimpleAlias])],El); // ToDo: jump to interface list
|
||||||
|
// check calling conventions
|
||||||
|
//writeln('TPasResolver.FinishClassType Intf=',GetObjPath(IntfProc),' Found=',GetObjPath(FindData.Found));
|
||||||
|
CheckProcSignatureMatch(IntfProc,TPasProcedure(FindData.Found),true);
|
||||||
|
|
||||||
Map.Procs[j]:=FindData.Found;
|
Map.Procs[j]:=FindData.Found;
|
||||||
end;
|
end;
|
||||||
Map:=Map.AncestorMap;
|
Map:=Map.AncestorMap;
|
||||||
@ -9396,7 +9401,7 @@ var
|
|||||||
DeclName, ImplName: String;
|
DeclName, ImplName: String;
|
||||||
ImplResult, DeclResult: TPasType;
|
ImplResult, DeclResult: TPasType;
|
||||||
ImplTemplType, DeclTemplType: TPasGenericTemplateType;
|
ImplTemplType, DeclTemplType: TPasGenericTemplateType;
|
||||||
NewImplPTMods: TProcTypeModifiers;
|
NewImplPTMods, DeclPTMods, ImplPTMods: TProcTypeModifiers;
|
||||||
ptm: TProcTypeModifier;
|
ptm: TProcTypeModifier;
|
||||||
NewImplProcMods: TProcedureModifiers;
|
NewImplProcMods: TProcedureModifiers;
|
||||||
pm: TProcedureModifier;
|
pm: TProcedureModifier;
|
||||||
@ -9409,6 +9414,9 @@ begin
|
|||||||
if DeclArgs.Count<>ImplArgs.Count then
|
if DeclArgs.Count<>ImplArgs.Count then
|
||||||
RaiseNotYetImplemented(20190912110642,ImplProc);
|
RaiseNotYetImplemented(20190912110642,ImplProc);
|
||||||
|
|
||||||
|
DeclPTMods:=DeclProc.ProcType.Modifiers;
|
||||||
|
ImplPTMods:=ImplProc.ProcType.Modifiers;
|
||||||
|
|
||||||
DeclTemplates:=GetProcTemplateTypes(DeclProc);
|
DeclTemplates:=GetProcTemplateTypes(DeclProc);
|
||||||
ImplTemplates:=GetProcTemplateTypes(ImplProc);
|
ImplTemplates:=GetProcTemplateTypes(ImplProc);
|
||||||
if DeclTemplates<>nil then
|
if DeclTemplates<>nil then
|
||||||
@ -9465,34 +9473,37 @@ begin
|
|||||||
if CheckElTypeCompatibility(ImplResult,DeclResult,prraSimple)>cGenericExact then
|
if CheckElTypeCompatibility(ImplResult,DeclResult,prraSimple)>cGenericExact then
|
||||||
RaiseIncompatibleType(20170216151734,nResultTypeMismatchExpectedButFound,
|
RaiseIncompatibleType(20170216151734,nResultTypeMismatchExpectedButFound,
|
||||||
[],DeclResult,ImplResult,ImplProc);
|
[],DeclResult,ImplResult,ImplProc);
|
||||||
|
|
||||||
if ImplProc.IsAsync and not DeclProc.IsAsync then
|
|
||||||
RaiseMsg(20200524111856,nXModifierMismatchY,sXModifierMismatchY,['procedure type','async'],ImplProc);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// calling convention
|
// calling convention
|
||||||
if ImplProc.CallingConvention<>DeclProc.CallingConvention then
|
if ImplProc.CallingConvention<>DeclProc.CallingConvention then
|
||||||
RaiseMsg(20170216151731,nCallingConventionMismatch,sCallingConventionMismatch,[],ImplProc);
|
RaiseMsg(20170216151731,nCallingConventionMismatch,sCallingConventionMismatch,[],ImplProc);
|
||||||
|
|
||||||
// proc modifiers
|
// modifiers
|
||||||
NewImplProcMods:=ImplProc.Modifiers-DeclProc.Modifiers-[pmAssembler];
|
if IsOverride then
|
||||||
if not IsOverride then
|
begin
|
||||||
|
// override/class-intf-impl: calling conventions must match
|
||||||
|
NewImplPTMods:=ImplPTMods><DeclPTMods;
|
||||||
|
for ptm in NewImplPTMods do
|
||||||
|
RaiseMsg(20201227213020,nXModifierMismatchY,sXModifierMismatchY,
|
||||||
|
['procedure type',ProcTypeModifiers[ptm]],ImplProc.ProcType);
|
||||||
|
end
|
||||||
|
else
|
||||||
begin
|
begin
|
||||||
// implementation proc must not add modifiers, except "assembler"
|
// implementation proc must not add modifiers, except "assembler"
|
||||||
|
NewImplProcMods:=ImplProc.Modifiers-DeclProc.Modifiers-[pmAssembler];
|
||||||
if NewImplProcMods<>[] then
|
if NewImplProcMods<>[] then
|
||||||
for pm in NewImplProcMods do
|
for pm in NewImplProcMods do
|
||||||
RaiseMsg(20200518182445,nDirectiveXNotAllowedHere,sDirectiveXNotAllowedHere,
|
RaiseMsg(20200518182445,nDirectiveXNotAllowedHere,sDirectiveXNotAllowedHere,
|
||||||
[ModifierNames[pm]],ImplProc.ProcType);
|
[ModifierNames[pm]],ImplProc.ProcType);
|
||||||
end;
|
|
||||||
|
|
||||||
// proc type modifiers
|
|
||||||
NewImplPTMods:=ImplProc.ProcType.Modifiers-DeclProc.ProcType.Modifiers;
|
|
||||||
// implementation proc must not add modifiers
|
// implementation proc must not add modifiers
|
||||||
|
NewImplPTMods:=ImplPTMods-DeclPTMods;
|
||||||
if NewImplPTMods<>[] then
|
if NewImplPTMods<>[] then
|
||||||
for ptm in NewImplPTMods do
|
for ptm in NewImplPTMods do
|
||||||
RaiseMsg(20200425154821,nDirectiveXNotAllowedHere,sDirectiveXNotAllowedHere,
|
RaiseMsg(20200425154821,nDirectiveXNotAllowedHere,sDirectiveXNotAllowedHere,
|
||||||
[ProcTypeModifiers[ptm]],ImplProc.ProcType);
|
[ProcTypeModifiers[ptm]],ImplProc.ProcType);
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.ResolveImplBlock(Block: TPasImplBlock);
|
procedure TPasResolver.ResolveImplBlock(Block: TPasImplBlock);
|
||||||
var
|
var
|
||||||
|
@ -3000,7 +3000,7 @@ begin
|
|||||||
'procedure TBird.Run<S>(a: TArray<S>);',
|
'procedure TBird.Run<S>(a: TArray<S>);',
|
||||||
'begin',
|
'begin',
|
||||||
' a:=TArray<S>(a);',
|
' a:=TArray<S>(a);',
|
||||||
//' F:=TArray<TObject>(a);',
|
' F:=TArray<TObject>(a);',
|
||||||
'end;',
|
'end;',
|
||||||
'']);
|
'']);
|
||||||
ParseUnit;
|
ParseUnit;
|
||||||
|
@ -890,6 +890,7 @@ type
|
|||||||
Procedure TestAsync_ProcTypeAsyncModMismatchFail;
|
Procedure TestAsync_ProcTypeAsyncModMismatchFail;
|
||||||
Procedure TestAsync_Inherited;
|
Procedure TestAsync_Inherited;
|
||||||
Procedure TestAsync_ClassInterface;
|
Procedure TestAsync_ClassInterface;
|
||||||
|
Procedure TestAsync_ClassInterface_AsyncMissmatchFail;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function LinesToStr(Args: array of const): string;
|
function LinesToStr(Args: array of const): string;
|
||||||
@ -32942,8 +32943,18 @@ begin
|
|||||||
' function _AddRef: longint;',
|
' function _AddRef: longint;',
|
||||||
' function _Release: longint;',
|
' function _Release: longint;',
|
||||||
' end;',
|
' end;',
|
||||||
|
'function Say(i: IUnknown): IUnknown; async;',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
'function Run: IUnknown; async;',
|
'function Run: IUnknown; async;',
|
||||||
'begin',
|
'begin',
|
||||||
|
' Result:=await(Run);',
|
||||||
|
' Result:=await(Run());',
|
||||||
|
' Result:=await(Run) as IUnknown;',
|
||||||
|
' Result:=await(Say(nil));',
|
||||||
|
' Result:=await(Say(await(Run())));',
|
||||||
|
' Result:=await(Say(await(Run()) as IUnknown));',
|
||||||
|
' Result:=await(Say(await(Run()) as IUnknown)) as IUnknown;',
|
||||||
'end;',
|
'end;',
|
||||||
'procedure Fly;',
|
'procedure Fly;',
|
||||||
'var p: TJSPromise;',
|
'var p: TJSPromise;',
|
||||||
@ -32959,8 +32970,25 @@ begin
|
|||||||
CheckSource('TestAsync_ClassInterface',
|
CheckSource('TestAsync_ClassInterface',
|
||||||
LinesToStr([ // statements
|
LinesToStr([ // statements
|
||||||
'rtl.createInterface(this, "IUnknown", "{D7ADB0E1-758A-322B-BDDF-21CD521DDFA9}", ["_AddRef", "_Release"], null);',
|
'rtl.createInterface(this, "IUnknown", "{D7ADB0E1-758A-322B-BDDF-21CD521DDFA9}", ["_AddRef", "_Release"], null);',
|
||||||
|
'this.Say = async function (i) {',
|
||||||
|
' var Result = null;',
|
||||||
|
' return Result;',
|
||||||
|
'};',
|
||||||
'this.Run = async function () {',
|
'this.Run = async function () {',
|
||||||
' var Result = null;',
|
' var Result = null;',
|
||||||
|
' var $ok = false;',
|
||||||
|
' try {',
|
||||||
|
' Result = rtl.setIntfL(Result, await $mod.Run());',
|
||||||
|
' Result = rtl.setIntfL(Result, await $mod.Run());',
|
||||||
|
' Result = rtl.setIntfL(Result, rtl.intfAsIntfT(await $mod.Run(), $mod.IUnknown));',
|
||||||
|
' Result = rtl.setIntfL(Result, await $mod.Say(null));',
|
||||||
|
' Result = rtl.setIntfL(Result, await $mod.Say(await $mod.Run()));',
|
||||||
|
' Result = rtl.setIntfL(Result, await $mod.Say(rtl.intfAsIntfT(await $mod.Run(), $mod.IUnknown)));',
|
||||||
|
' Result = rtl.setIntfL(Result, rtl.intfAsIntfT(await $mod.Say(rtl.intfAsIntfT(await $mod.Run(), $mod.IUnknown)), $mod.IUnknown));',
|
||||||
|
' $ok = true;',
|
||||||
|
' } finally {',
|
||||||
|
' if (!$ok) rtl._Release(Result);',
|
||||||
|
' };',
|
||||||
' return Result;',
|
' return Result;',
|
||||||
'};',
|
'};',
|
||||||
'this.Fly = function () {',
|
'this.Fly = function () {',
|
||||||
@ -32976,6 +33004,29 @@ begin
|
|||||||
CheckResolverUnexpectedHints();
|
CheckResolverUnexpectedHints();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestAsync_ClassInterface_AsyncMissmatchFail;
|
||||||
|
begin
|
||||||
|
StartProgram(true,[supTInterfacedObject]);
|
||||||
|
Add([
|
||||||
|
'{$mode objfpc}',
|
||||||
|
'{$modeswitch externalclass}',
|
||||||
|
'type',
|
||||||
|
' TJSPromise = class external name ''Promise''',
|
||||||
|
' end;',
|
||||||
|
' IBird = interface',
|
||||||
|
' procedure Run;',
|
||||||
|
' end;',
|
||||||
|
' TBird = class(TInterfacedObject,IBird)',
|
||||||
|
' procedure Run; async;',
|
||||||
|
' end;',
|
||||||
|
'procedure TBird.Run;',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'begin',
|
||||||
|
' ']);
|
||||||
|
SetExpectedPasResolverError('procedure type modifier "async" mismatch',nXModifierMismatchY);
|
||||||
|
ConvertProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
Initialization
|
Initialization
|
||||||
RegisterTests([TTestModule]);
|
RegisterTests([TTestModule]);
|
||||||
|
Loading…
Reference in New Issue
Block a user