* give an error when trying to call an object instance method via a type node

(mantis #34821)

git-svn-id: trunk@40785 -
This commit is contained in:
Jonas Maebe 2019-01-06 15:21:36 +00:00
parent 078d8e9d2a
commit b2b34338e5
6 changed files with 690 additions and 603 deletions

1
.gitattributes vendored
View File

@ -14760,6 +14760,7 @@ tests/webtbf/tw34691.pp svneol=native#text/pascal
tests/webtbf/tw3473.pp svneol=native#text/plain
tests/webtbf/tw3480.pp svneol=native#text/plain
tests/webtbf/tw3480a.pp svneol=native#text/plain
tests/webtbf/tw34821.pp svneol=native#text/plain
tests/webtbf/tw3488.pp svneol=native#text/plain
tests/webtbf/tw3495.pp svneol=native#text/plain
tests/webtbf/tw3502.pp svneol=native#text/plain

View File

@ -1582,6 +1582,18 @@ parser_w_operator_overloaded_hidden_3=03347_W_Operator overload hidden by intern
% (in case of dynamic arrays that is the modeswitch \var{ArrayOperators}).
parser_e_threadvar_must_be_class=03348_E_Thread variables inside classes or records must be class variables
% A \var{threadvar} section inside a class or record was started without it being prefixed by \var{class}.
parser_e_only_static_members_via_object_type=03349_E_Only static methods and static variables can be referenced through an object type
% This error occurs in a situation like the following:
% \begin{verbatim}
% Type
% TObj = object
% procedure test;
% end;
%
% begin
% TObj.test;
% \end{verbatim}
% \var{test} is not a static method and hence cannot be called through a type, but only using an instance.
%
%
% \end{description}

View File

@ -459,6 +459,7 @@ const
parser_e_invalid_internal_function_index=03346;
parser_w_operator_overloaded_hidden_3=03347;
parser_e_threadvar_must_be_class=03348;
parser_e_only_static_members_via_object_type=03349;
type_e_mismatch=04000;
type_e_incompatible_types=04001;
type_e_not_equal_types=04002;
@ -1106,9 +1107,9 @@ const
option_info=11024;
option_help_pages=11025;
MsgTxtSize = 82706;
MsgTxtSize = 82796;
MsgIdxMax : array[1..20] of longint=(
28,106,349,126,99,59,142,34,221,67,
28,106,350,126,99,59,142,34,221,67,
62,20,30,1,1,1,1,1,1,1
);

File diff suppressed because it is too large Load Diff

View File

@ -1281,6 +1281,7 @@ implementation
var
isclassref:boolean;
isrecordtype:boolean;
isobjecttype:boolean;
begin
if sym=nil then
begin
@ -1301,11 +1302,13 @@ implementation
do_typecheckpass(p1);
isclassref:=(p1.resultdef.typ=classrefdef);
isrecordtype:=(p1.nodetype=typen) and (p1.resultdef.typ=recorddef);
isobjecttype:=(p1.nodetype=typen) and is_object(p1.resultdef);
end
else
begin
isclassref:=false;
isrecordtype:=false;
isobjecttype:=false;
end;
if assigned(spezcontext) and not (sym.typ=procsym) then
@ -1325,16 +1328,47 @@ implementation
if (
isclassref or
(
isrecordtype and
(isobjecttype or
isrecordtype) and
not (cnf_inherited in callflags)
)
) and
(p1.nodetype=calln) and
assigned(tcallnode(p1).procdefinition) then
begin
if not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and
not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
Message(parser_e_only_class_members_via_class_ref);
if not isobjecttype then
begin
if not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and
not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
Message(parser_e_only_class_members_via_class_ref);
end
else
begin
{ with objects, you can also do this:
type
tparent = object
procedure test;
end;
tchild = object(tchild)
procedure test;
end;
procedure tparent.test;
begin
end;
procedure tchild.test;
begin
tparent.test;
end;
}
if (tcallnode(p1).procdefinition.proctypeoption<>potype_constructor) and
not(po_staticmethod in tcallnode(p1).procdefinition.procoptions) and
(not assigned(current_structdef) or
not def_is_related(current_structdef,structh)) then
Message(parser_e_only_static_members_via_object_type);
end;
{ in Java, constructors are not automatically inherited
-> calling a constructor from a parent type will create
an instance of that parent type! }
@ -1352,7 +1386,7 @@ implementation
assigned(tcallnode(p1).methodpointer) and
(tcallnode(p1).methodpointer.nodetype=loadvmtaddrn) then
Message1(type_w_instance_abstract_class,structh.RttiName);
end;
end
end;
fieldvarsym:
begin
@ -1366,7 +1400,9 @@ implementation
(current_procinfo.procdef.struct=structh))) then
Message(parser_e_only_class_members)
else
Message(parser_e_only_class_members_via_class_ref);
Message(parser_e_only_class_members_via_class_ref)
else if isobjecttype then
Message(parser_e_only_static_members_via_object_type);
p1:=csubscriptnode.create(sym,p1);
end;
end;

29
tests/webtbf/tw34821.pp Normal file
View File

@ -0,0 +1,29 @@
{ %fail }
unit tw34821;
{$mode objfpc}{$H+}
interface
type TStrBuilder = class
procedure append(); inline;
end;
type TTest = object
procedure xyz;
end;
implementation
procedure TStrBuilder.append();
begin
TTest.xyz;
end;
procedure TTest.xyz;
begin
end;
end.