소스 검색

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 -

paul 14 년 전
부모
커밋
0c9b40acb7
8개의 변경된 파일292개의 추가작업 그리고 253개의 파일을 삭제
  1. 1 0
      .gitattributes
  2. 2 14
      compiler/defcmp.pas
  3. 3 3
      compiler/msg/errore.msg
  4. 1 1
      compiler/msgidx.inc
  5. 230 230
      compiler/msgtxt.inc
  6. 4 1
      compiler/pdecsub.pas
  7. 27 4
      compiler/symtable.pas
  8. 24 0
      tests/test/toperator12.pp

+ 1 - 0
.gitattributes

@@ -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

+ 2 - 14
compiler/defcmp.pas

@@ -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;

+ 3 - 3
compiler/msg/errore.msg

@@ -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. 

+ 1 - 1
compiler/msgidx.inc

@@ -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,

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 230 - 230
compiler/msgtxt.inc


+ 4 - 1
compiler/pdecsub.pas

@@ -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

+ 27 - 4
compiler/symtable.pas

@@ -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 - 0
tests/test/toperator12.pp

@@ -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.

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.