diff --git a/.gitattributes b/.gitattributes index 6968acacd5..fc311b2657 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10874,6 +10874,7 @@ tests/tbs/tb0613.pp svneol=native#text/pascal tests/tbs/tb0614.pp svneol=native#text/pascal tests/tbs/tb0615.pp svneol=native#text/pascal tests/tbs/tb0616.pp svneol=native#text/pascal +tests/tbs/tb0617.pp svneol=native#text/pascal tests/tbs/tb205.pp svneol=native#text/plain tests/tbs/tb610.pp svneol=native#text/pascal tests/tbs/tb613.pp svneol=native#text/plain diff --git a/compiler/pstatmnt.pas b/compiler/pstatmnt.pas index d1ba14ff08..0f3e232b7b 100644 --- a/compiler/pstatmnt.pas +++ b/compiler/pstatmnt.pas @@ -1287,59 +1287,54 @@ implementation if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then maybe_call_procvar(p,false); - { additional checks make no sense in a generic definition } - if not(df_generic in current_procinfo.procdef.defoptions) then + { blockn support because a read/write is changed into a blocknode + with a separate statement for each read/write operation (JM) + the same is true for val() if the third parameter is not 32 bit + + goto nodes are created by the compiler for non local exit statements, so + include them as well + } + if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen, + continuen,labeln,blockn,exitn,goton]) or + ((p.nodetype=inlinen) and + not is_void(p.resultdef)) or + ((p.nodetype=calln) and + (assigned(tcallnode(p).procdefinition)) and + (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then + Message(parser_e_illegal_expression); + + if not assigned(p.resultdef) then + do_typecheckpass(p); + + { Specify that we don't use the value returned by the call. + This is used for : + - dispose of temp stack space + - dispose on FPU stack + - extended syntax checking } + if (p.nodetype=calln) then begin - { blockn support because a read/write is changed into a blocknode - with a separate statement for each read/write operation (JM) - the same is true for val() if the third parameter is not 32 bit + exclude(tcallnode(p).callnodeflags,cnf_return_value_used); - goto nodes are created by the compiler for non local exit statements, so - include them as well - } - if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen, - continuen,labeln,blockn,exitn,goton]) or - ((p.nodetype=inlinen) and - not is_void(p.resultdef)) or - ((p.nodetype=calln) and - (assigned(tcallnode(p).procdefinition)) and - (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then + { in $x- state, the function result must not be ignored } + if not(cs_extsyntax in current_settings.moduleswitches) and + not(is_void(p.resultdef)) and + { can be nil in case there was an error in the expression } + assigned(tcallnode(p).procdefinition) and + { allow constructor calls to drop the result if they are + called as instance methods instead of class methods } + not( + (tcallnode(p).procdefinition.proctypeoption=potype_constructor) and + is_class_or_object(tprocdef(tcallnode(p).procdefinition).struct) and + assigned(tcallnode(p).methodpointer) and + (tnode(tcallnode(p).methodpointer).resultdef.typ=objectdef) + ) then Message(parser_e_illegal_expression); - - if not assigned(p.resultdef) then - do_typecheckpass(p); - - { Specify that we don't use the value returned by the call. - This is used for : - - dispose of temp stack space - - dispose on FPU stack - - extended syntax checking } - if (p.nodetype=calln) then - begin - exclude(tcallnode(p).callnodeflags,cnf_return_value_used); - - { in $x- state, the function result must not be ignored } - if not(cs_extsyntax in current_settings.moduleswitches) and - not(is_void(p.resultdef)) and - { can be nil in case there was an error in the expression } - assigned(tcallnode(p).procdefinition) and - { allow constructor calls to drop the result if they are - called as instance methods instead of class methods } - not( - (tcallnode(p).procdefinition.proctypeoption=potype_constructor) and - is_class_or_object(tprocdef(tcallnode(p).procdefinition).struct) and - assigned(tcallnode(p).methodpointer) and - (tnode(tcallnode(p).methodpointer).resultdef.typ=objectdef) - ) then - Message(parser_e_illegal_expression); - end; end; + code:=p; end; end; - if assigned(code) and - { type checking makes no sense in a generic definition } - not(df_generic in current_procinfo.procdef.defoptions) then + if assigned(code) then begin typecheckpass(code); code.fileinfo:=filepos; diff --git a/compiler/psub.pas b/compiler/psub.pas index 1f1804ef2b..ba21632816 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -1869,9 +1869,7 @@ implementation entrypos:=code.fileinfo; { Finish type checking pass } - { type checking makes no sense in a generic definition } - if not(df_generic in current_procinfo.procdef.defoptions) then - do_typecheckpass(code); + do_typecheckpass(code); if assigned(procdef.parentfpinitblock) then begin diff --git a/tests/tbs/tb0617.pp b/tests/tbs/tb0617.pp new file mode 100644 index 0000000000..029b49b572 --- /dev/null +++ b/tests/tbs/tb0617.pp @@ -0,0 +1,37 @@ +{ %NORUN } + +program tb0617; + +{$mode objfpc} + +type + generic TGenericStructList = class + public + function Remove(const Item: T): Integer; + procedure Delete(Index: Integer); + function IndexOf(const Item: T): Integer; + end; + +function TGenericStructList.Remove(const Item: T): Integer; +begin + Result := IndexOf(Item); + { for some reason, FPC 3.1.1 makes here incorrect warning: + castlegenericlists.pas(254,13) Warning: Function result variable does not seem to be initialized } + if Result >= 0 then + Delete(Result); +end; + +function TGenericStructList.IndexOf(const Item: T): Integer; +begin + Result := 0; +end; + +procedure TGenericStructList.Delete(Index: Integer); +begin + +end; + + +begin + +end.