compiler: record operators

- allow operator also if return type match the structure type (before at least one parameter had to match)
  - search both operands symbol tables for a suitable assignment operator
  - test
based on patch of Blaise Thorn (issue #0018490)

git-svn-id: trunk@16762 -
This commit is contained in:
paul 2011-01-14 02:25:48 +00:00
parent 8a7b10586d
commit 0c9b40acb7
8 changed files with 316 additions and 278 deletions

1
.gitattributes vendored
View File

@ -9619,6 +9619,7 @@ tests/test/tobject8.pp svneol=native#text/plain
tests/test/toperator1.pp svneol=native#text/plain
tests/test/toperator10.pp svneol=native#text/pascal
tests/test/toperator11.pp svneol=native#text/pascal
tests/test/toperator12.pp svneol=native#text/pascal
tests/test/toperator2.pp svneol=native#text/plain
tests/test/toperator3.pp svneol=native#text/plain
tests/test/toperator4.pp svneol=native#text/plain

View File

@ -29,7 +29,7 @@ interface
cclasses,
globtype,globals,
node,
symconst,symtype,symbase,symdef;
symconst,symtype,symdef;
type
{ if acp is cp_all the var const or nothing are considered equal }
@ -1487,19 +1487,7 @@ implementation
)
) then
begin
{ search record/object symtable first for a sutable operator }
if def_from.typ in [recorddef,objectdef] then
symtablestack.push(tabstractrecorddef(def_from).symtable);
{ if type conversion is explicit then search first for explicit
operator overload and if not found then use implicit operator }
if cdo_explicit in cdoptions then
operatorpd:=search_assignment_operator(def_from,def_to,true)
else
operatorpd:=nil;
if operatorpd=nil then
operatorpd:=search_assignment_operator(def_from,def_to,false);
if def_from.typ in [recorddef,objectdef] then
symtablestack.pop(tabstractrecorddef(def_from).symtable);
operatorpd:=search_assignment_operator(def_from,def_to,cdo_explicit in cdoptions);
if assigned(operatorpd) then
eq:=te_convert_operator;
end;

View File

@ -1360,9 +1360,9 @@ parser_e_class_methods_only_static_in_records=03301_E_Class methods must be stat
parser_e_no_constructor_in_records=03302_E_Constructors aren't allowed in records
% Constructor declarations aren't allowed in records.
% \end{description}
parser_e_at_least_one_argument_must_be_of_type=03303_E_At least one argument must be of type "$1"
% It is required that at least one argument be of type of structure where this method is defined.
% For example class operators must contain at least one argument of the structure where they are defined.
parser_e_at_least_one_argument_must_be_of_type=03303_E_Either the result or at least one parameter must be of type "$1"
% It is required that either the result of the routine or at least one of its parameters be of the specified type.
% For example class operators either take an instance of the structuted type in which they are defined, or they return one.
parser_e_cant_use_type_parameters_here=03304_E_Type parameters may require initialization/finalization - can't be used in variant records
% Type parameters may be specialized with types which (e.g. \var{ansistring}) need initialization/finalization
% code which is implicitly generated by the compiler.

View File

@ -882,7 +882,7 @@ const
option_info=11024;
option_help_pages=11025;
MsgTxtSize = 58664;
MsgTxtSize = 58686;
MsgIdxMax : array[1..20] of longint=(
24,88,305,99,84,54,111,22,202,63,

File diff suppressed because it is too large Load Diff

View File

@ -1443,7 +1443,10 @@ implementation
else
begin
read_returndef(pd);
if (po_classmethod in pd.procoptions) then
{ check that class operators have either return type of structure or }
{ at least one argument of that type }
if (po_classmethod in pd.procoptions) and
(pd.returndef <> pd.struct) then
begin
found:=false;
for i := 0 to pd.parast.SymList.Count - 1 do

View File

@ -2286,9 +2286,7 @@ implementation
end;
function search_assignment_operator(from_def,to_def:Tdef;explicit:boolean):Tprocdef;
const
op_token:array[boolean] of ttoken=(_ASSIGNMENT,_OP_EXPLICIT);
function search_specific_assignment_operator(assignment_type:ttoken;from_def,to_def:Tdef):Tprocdef;
var
sym : Tprocsym;
hashedid : THashedIDString;
@ -2298,7 +2296,7 @@ implementation
bestpd : tprocdef;
stackitem : psymtablestackitem;
begin
hashedid.id:=overloaded_names[op_token[explicit]];
hashedid.id:=overloaded_names[assignment_type];
besteq:=te_incompatible;
bestpd:=nil;
stackitem:=symtablestack.stack;
@ -2326,6 +2324,31 @@ implementation
end;
function search_assignment_operator(from_def,to_def:Tdef;explicit:boolean):Tprocdef;
begin
{ search record/object symtable first for a suitable operator }
if from_def.typ in [recorddef,objectdef] then
symtablestack.push(tabstractrecorddef(from_def).symtable);
if to_def.typ in [recorddef,objectdef] then
symtablestack.push(tabstractrecorddef(to_def).symtable);
{ if type conversion is explicit then search first for explicit
operator overload and if not found then use implicit operator }
if explicit then
result:=search_specific_assignment_operator(_OP_EXPLICIT,from_def,to_def)
else
result:=nil;
if result=nil then
result:=search_specific_assignment_operator(_ASSIGNMENT,from_def,to_def);
{ restore symtable stack }
if to_def.typ in [recorddef,objectdef] then
symtablestack.pop(tabstractrecorddef(to_def).symtable);
if from_def.typ in [recorddef,objectdef] then
symtablestack.pop(tabstractrecorddef(from_def).symtable);
end;
function search_enumerator_operator(from_def,to_def:Tdef): Tprocdef;
var
sym : Tprocsym;

24
tests/test/toperator12.pp Normal file
View File

@ -0,0 +1,24 @@
program toperator12;
{$ifdef FPC}
{$mode Delphi}
{$endif}
type
R = record
F: Integer;
class operator Implicit(const v: integer): R;
end;
class operator R.Implicit(const v: integer): R;
begin
Result.F := v;
end;
var
x: R;
begin
x := 42;
if x.F <> 42 then
halt(1);
end.