Przeglądaj źródła

compiler: implement record methods and class methods:
- rename tprocdef._class to tprocdef.struct and change the type from tobjectdef to tabstractrecorddef because methods can belong not to classes only now but to records too
- replace in many places use of current_objectdef to current_structdef with typcast where is needed
- add an argument to comp_expr, expr, factor, sub_expr to notify that we are searching type only symbol to solve the problem with records,objects,classes which contains fields with the same name as previosly declared type (like:
HWND = type Handle;
rec = record
hWnd: HWND;
end;)
- disable check in factor_read_id which was made for object that only static fields can be accessed as TObjectType.FieldName outside the object because it makes SizeOf(TObjectType.FieldName) imposible and since the same method was extended to handle records it also breaks a52 package compilation
- rename tcallcandidates.collect_overloads_in_class to tcallcandidates.collect_overloads_in_struct and addapt the code to handle overloads in records too
- fix searchsym_type to search also in object ancestors if we found an object symtable
- add pd_record, pd_notrecord flags to mark procedure modifies which can or can't be used with records. Disallow the next modifiers for records: abstract, dynamic, export, external, far, far16, final, forward, internconst, internproc, interrupt, message, near, override, public, reintroduce, virtual, weakexternal,
Allow the next modifiers for records: static

git-svn-id: branches/paul/extended_records@16526 -

paul 14 lat temu
rodzic
commit
56bf42de57

+ 2 - 2
compiler/dbgdwarf.pas

@@ -2034,7 +2034,7 @@ implementation
         def.dbg_state:=dbg_state_writing;
 
         current_asmdata.asmlists[al_dwarf_info].concat(tai_comment.Create(strpnew('Procdef '+def.fullprocname(true))));
-        if not is_objc_class_or_protocol(def._class) then
+        if not is_objc_class_or_protocol(def.struct) then
           append_entry(DW_TAG_subprogram,true,
             [DW_AT_name,DW_FORM_string,symname(def.procsym)+#0
             { data continues below }
@@ -2065,7 +2065,7 @@ implementation
           append_attribute(DW_AT_external,DW_FORM_flag,[true]);
         { Abstract or virtual/overriding method.  }
         if (([po_abstractmethod, po_virtualmethod, po_overridingmethod] * def.procoptions) <> []) and
-           not is_objc_class_or_protocol(def._class) then
+           not is_objc_class_or_protocol(def.struct) then
           begin
             if not(po_abstractmethod in def.procoptions) then
               append_attribute(DW_AT_virtuality,DW_FORM_data1,[ord(DW_VIRTUALITY_virtual)])

+ 7 - 7
compiler/dbgstabs.pas

@@ -66,7 +66,7 @@ interface
         procedure write_sym_stabstr(list:TAsmList;sym:tsym;const ss:ansistring);
         { tdef writing }
         function  def_stab_number(def:tdef):string;
-        function  def_stab_classnumber(def:tobjectdef):string;
+        function  def_stab_classnumber(def:tabstractrecorddef):string;
         function  def_var_value(const s:string;arg:pointer):string;
         function  def_stabstr_evaluate(def:tdef;const s:string;const vars:array of string):ansistring;
         procedure write_def_stabstr(list:TAsmList;def:tdef;const ss:ansistring);
@@ -314,11 +314,11 @@ implementation
       end;
 
 
-    function TDebugInfoStabs.def_stab_classnumber(def:tobjectdef):string;
+    function TDebugInfoStabs.def_stab_classnumber(def:tabstractrecorddef):string;
       begin
         if def.stab_number=0 then
           def_stab_number(def);
-        if (def.objecttype=odt_class) then
+        if (def.typ=objectdef) and (tobjectdef(def).objecttype=odt_class) then
           result:=tostr(def.stab_number-1)
         else
           result:=tostr(def.stab_number);
@@ -414,7 +414,7 @@ implementation
                lindex := pd.extnumber;
                {doesnt seem to be necessary
                lindex := lindex or $80000000;}
-               virtualind := '*'+tostr(lindex)+';'+def_stab_classnumber(pd._class)+';'
+               virtualind := '*'+tostr(lindex)+';'+def_stab_classnumber(pd.struct)+';'
              end
             else
              virtualind := '.';
@@ -1345,13 +1345,13 @@ implementation
                 end
             else
               begin
-                if not(is_class(tprocdef(sym.owner.defowner)._class)) then
+                if not(is_class(tprocdef(sym.owner.defowner).struct)) then
                   c:='v'
                 else
                   c:='p';
                 if (sym.localloc.loc=LOC_REFERENCE) then
                   ss:=sym_stabstr_evaluate(sym,'"$$t:$1",${N_TSYM},0,0,$2',
-                        [c+def_stab_number(tprocdef(sym.owner.defowner)._class),tostr(sym.localloc.reference.offset)])
+                        [c+def_stab_number(tprocdef(sym.owner.defowner).struct),tostr(sym.localloc.reference.offset)])
                 else
                   begin
                     if (c='p') then
@@ -1360,7 +1360,7 @@ implementation
                       c:='a';
                     regidx:=findreg_by_number(sym.localloc.register);
                     ss:=sym_stabstr_evaluate(sym,'"$$t:$1",${N_RSYM},0,0,$2',
-                        [c+def_stab_number(tprocdef(sym.owner.defowner)._class),tostr(regstabs_table[regidx])]);
+                        [c+def_stab_number(tprocdef(sym.owner.defowner).struct),tostr(regstabs_table[regidx])]);
                   end
               end;
           end

+ 19 - 16
compiler/htypechk.pas

@@ -66,7 +66,7 @@ interface
         FParaNode   : tnode;
         FParaLength : smallint;
         FAllowVariant : boolean;
-        procedure collect_overloads_in_class(ProcdefOverloadList:TFPObjectList);
+        procedure collect_overloads_in_struct(ProcdefOverloadList:TFPObjectList);
         procedure collect_overloads_in_units(ProcdefOverloadList:TFPObjectList; objcidcall,explicitunit: boolean);
         procedure create_candidate_list(ignorevisibility,allowdefaultparas,objcidcall,explicitunit:boolean);
         function  proc_add(ps:tprocsym;pd:tprocdef;objcidcall: boolean):pcandidate;
@@ -1714,21 +1714,21 @@ implementation
       end;
 
 
-    procedure tcallcandidates.collect_overloads_in_class(ProcdefOverloadList:TFPObjectList);
+    procedure tcallcandidates.collect_overloads_in_struct(ProcdefOverloadList:TFPObjectList);
       var
         j          : integer;
         pd         : tprocdef;
         srsym      : tsym;
-        objdef     : tobjectdef;
+        structdef  : tabstractrecorddef;
         hashedid   : THashedIDString;
         hasoverload : boolean;
       begin
-        objdef:=tobjectdef(fprocsym.owner.defowner);
+        structdef:=tabstractrecorddef(fprocsym.owner.defowner);
         hashedid.id:=fprocsym.name;
         hasoverload:=false;
-        while assigned(objdef) do
+        while assigned(structdef) do
          begin
-           srsym:=tprocsym(objdef.symtable.FindWithHash(hashedid));
+           srsym:=tprocsym(structdef.symtable.FindWithHash(hashedid));
            if assigned(srsym) and
               { Delphi allows hiding a property by a procedure with the same name }
               (srsym.typ=procsym) then
@@ -1747,7 +1747,10 @@ implementation
                  break;
              end;
            { next parent }
-           objdef:=objdef.childof;
+           if (structdef.typ=objectdef) then
+             structdef:=tobjectdef(structdef).childof
+           else
+             structdef:=nil;
          end;
       end;
 
@@ -1830,7 +1833,7 @@ implementation
         hp    : pcandidate;
         pt    : tcallparanode;
         found : boolean;
-        contextobjdef : tobjectdef;
+        contextstructdef : tabstractrecorddef;
         ProcdefOverloadList : TFPObjectList;
       begin
         FCandidateProcs:=nil;
@@ -1839,8 +1842,8 @@ implementation
         ProcdefOverloadList:=TFPObjectList.Create(false);
         if not objcidcall and
            (FOperator=NOTOKEN) and
-           (FProcsym.owner.symtabletype=objectsymtable) then
-          collect_overloads_in_class(ProcdefOverloadList)
+           (FProcsym.owner.symtabletype in [objectsymtable,recordsymtable]) then
+          collect_overloads_in_struct(ProcdefOverloadList)
         else
           collect_overloads_in_units(ProcdefOverloadList,objcidcall,explicitunit);
 
@@ -1864,15 +1867,15 @@ implementation
           units. At least kylix supports it this way (PFV) }
         if assigned(FProcSymtable) and
            (
-            (FProcSymtable.symtabletype=ObjectSymtable) or
+            (FProcSymtable.symtabletype in [ObjectSymtable,recordsymtable]) or
             ((FProcSymtable.symtabletype=withsymtable) and
-             (FProcSymtable.defowner.typ=objectdef))
+             (FProcSymtable.defowner.typ in [objectdef,recorddef]))
            ) and
            (FProcSymtable.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
            FProcSymtable.defowner.owner.iscurrentunit then
-          contextobjdef:=tobjectdef(FProcSymtable.defowner)
+          contextstructdef:=tabstractrecorddef(FProcSymtable.defowner)
         else
-          contextobjdef:=current_objectdef;
+          contextstructdef:=current_structdef;
 
         { Process all found overloads }
         for j:=0 to ProcdefOverloadList.Count-1 do
@@ -1897,8 +1900,8 @@ implementation
                ) and
                (
                 ignorevisibility or
-                (pd.owner.symtabletype<>objectsymtable) or
-                is_visible_for_object(pd,contextobjdef)
+                not (pd.owner.symtabletype in [objectsymtable,recordsymtable]) or
+                is_visible_for_object(pd,contextstructdef)
                ) then
               begin
                 { don't add duplicates, only compare visible parameters for the user }

+ 3 - 3
compiler/i386/cgcpu.pas

@@ -617,7 +617,7 @@ unit cgcpu;
           if (procdef.extnumber=$ffff) then
             Internalerror(200006139);
           { call/jmp  vmtoffs(%eax) ; method offs }
-          reference_reset_base(href,NR_EAX,procdef._class.vmtmethodoffset(procdef.extnumber),4);
+          reference_reset_base(href,NR_EAX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4);
           list.concat(taicpu.op_ref(op,S_L,href));
         end;
 
@@ -629,7 +629,7 @@ unit cgcpu;
           if (procdef.extnumber=$ffff) then
             Internalerror(200006139);
           { mov vmtoffs(%eax),%eax ; method offs }
-          reference_reset_base(href,NR_EAX,procdef._class.vmtmethodoffset(procdef.extnumber),4);
+          reference_reset_base(href,NR_EAX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4);
           cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
         end;
 
@@ -641,7 +641,7 @@ unit cgcpu;
       begin
         if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
           Internalerror(200006137);
-        if not assigned(procdef._class) or
+        if not assigned(procdef.struct) or
            (procdef.procoptions*[po_classmethod, po_staticmethod,
              po_methodpointer, po_interrupt, po_iocheck]<>[]) then
           Internalerror(200006138);

+ 3 - 2
compiler/ncal.pas

@@ -1671,7 +1671,8 @@ implementation
             begin
               if (procdefinition.typ<>procdef) then
                 internalerror(200305062);
-              if (oo_has_vmt in tprocdef(procdefinition)._class.objectoptions) then
+              if (tprocdef(procdefinition).struct.typ=objectdef) and
+                 (oo_has_vmt in tobjectdef(tprocdef(procdefinition).struct).objectoptions) then
                 begin
                   { we only need the vmt, loading self is not required and there is no
                     need to check for typen, because that will always get the
@@ -2871,7 +2872,7 @@ implementation
               error and to prevent users from generating non-working code
               when they expect to clone the current instance, see bug 3662 (PFV) }
               if (procdefinition.proctypeoption=potype_constructor) and
-                 is_class(tprocdef(procdefinition)._class) and
+                 is_class(tprocdef(procdefinition).struct) and
                  assigned(methodpointer) and
                  (nf_is_self in methodpointer.flags) then
                 resultdef:=voidtype

+ 7 - 7
compiler/ncgcal.pas

@@ -688,12 +688,12 @@ implementation
                 (methodpointer.nodetype<>typen) and
                 (not assigned(current_procinfo) or
                  wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
-               tprocdef(procdefinition)._class.register_vmt_call(tprocdef(procdefinition).extnumber);
+               tobjectdef(tprocdef(procdefinition).struct).register_vmt_call(tprocdef(procdefinition).extnumber);
 {$ifdef vtentry}
              if not is_interface(tprocdef(procdefinition)._class) then
                begin
                  inc(current_asmdata.NextVTEntryNr);
-                 current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+tprocdef(procdefinition)._class.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(pint)),AT_FUNCTION,0));
+                 current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+tprocdef(procdefinition).struct.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(pint)),AT_FUNCTION,0));
                end;
 {$endif vtentry}
 
@@ -725,16 +725,16 @@ implementation
                    end;
 
                  { test validity of VMT }
-                 if not(is_interface(tprocdef(procdefinition)._class)) and
-                    not(is_cppclass(tprocdef(procdefinition)._class)) then
-                   cg.g_maybe_testvmt(current_asmdata.CurrAsmList,vmtreg,tprocdef(procdefinition)._class);
+                 if not(is_interface(tprocdef(procdefinition).struct)) and
+                    not(is_cppclass(tprocdef(procdefinition).struct)) then
+                   cg.g_maybe_testvmt(current_asmdata.CurrAsmList,vmtreg,tobjectdef(tprocdef(procdefinition).struct));
 
                  { Call through VMT, generate a VTREF symbol to notify the linker }
-                 vmtoffset:=tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber);
+                 vmtoffset:=tobjectdef(tprocdef(procdefinition).struct).vmtmethodoffset(tprocdef(procdefinition).extnumber);
                  { register call for WPO }
                  if (not assigned(current_procinfo) or
                      wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
-                   tprocdef(procdefinition)._class.register_vmt_call(tprocdef(procdefinition).extnumber);
+                   tobjectdef(tprocdef(procdefinition).struct).register_vmt_call(tprocdef(procdefinition).extnumber);
 {$ifndef x86}
                  pvreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_ADDR);
 {$endif not x86}

+ 3 - 3
compiler/ncgld.pas

@@ -500,9 +500,9 @@ implementation
                        begin
                          if (not assigned(current_procinfo) or
                              wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
-                           procdef._class.register_vmt_call(procdef.extnumber);
+                           tobjectdef(procdef.struct).register_vmt_call(procdef.extnumber);
             {$ifdef vtentry}
-                         if not is_interface(procdef._class) then
+                         if not is_interface(procdef.struct) then
                            begin
                              inc(current_asmdata.NextVTEntryNr);
                              current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+procdef._class.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(pint)),AT_FUNCTION,0));
@@ -517,7 +517,7 @@ implementation
                              cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
                            end;
                          { load method address }
-                         reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber),sizeof(pint));
+                         reference_reset_base(href,hregister,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
                          hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
                          cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
                          { ... and store it }

+ 2 - 2
compiler/ncgrtti.pas

@@ -318,9 +318,9 @@ implementation
                   begin
                      { virtual method, write vmt offset }
                      current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,
-                       tprocdef(propaccesslist.procdef)._class.vmtmethodoffset(tprocdef(propaccesslist.procdef).extnumber)));
+                       tobjectdef(tprocdef(propaccesslist.procdef).struct).vmtmethodoffset(tprocdef(propaccesslist.procdef).extnumber)));
                      { register for wpo }
-                     tprocdef(propaccesslist.procdef)._class.register_vmt_call(tprocdef(propaccesslist.procdef).extnumber);
+                     tobjectdef(tprocdef(propaccesslist.procdef).struct).register_vmt_call(tprocdef(propaccesslist.procdef).extnumber);
                      {$ifdef vtentry}
                      { not sure if we can insert those vtentry symbols safely here }
                      {$error register methods used for published properties}

+ 1 - 1
compiler/nflw.pas

@@ -383,7 +383,7 @@ implementation
                  ccallparanode.create(caddrnode.create(ctemprefnode.create(state)),nil)
                )
              );
-         sym:=search_class_member(objc_fastenumeration,'COUNTBYENUMERATINGWITHSTATE_OBJECTS_COUNT');
+         sym:=search_struct_member(objc_fastenumeration,'COUNTBYENUMERATINGWITHSTATE_OBJECTS_COUNT');
          if not assigned(sym) or
             (sym.typ<>procsym) then
            internalerror(2010061901);

+ 3 - 3
compiler/nld.pas

@@ -301,17 +301,17 @@ implementation
                  definition }
                if vo_is_self in tabstractvarsym(symtableentry).varoptions then
                  begin
-                   resultdef:=tprocdef(symtableentry.owner.defowner)._class;
+                   resultdef:=tprocdef(symtableentry.owner.defowner).struct;
                    if (po_classmethod in tprocdef(symtableentry.owner.defowner).procoptions) or
                       (po_staticmethod in tprocdef(symtableentry.owner.defowner).procoptions) then
                      resultdef:=tclassrefdef.create(resultdef)
-                   else if is_object(resultdef) and
+                   else if (is_object(resultdef) or is_record(resultdef)) and
                            (nf_load_self_pointer in flags) then
                      resultdef:=tpointerdef.create(resultdef);
                  end
                else if vo_is_vmt in tabstractvarsym(symtableentry).varoptions then
                  begin
-                   resultdef:=tprocdef(symtableentry.owner.defowner)._class;
+                   resultdef:=tprocdef(symtableentry.owner.defowner).struct;
                    resultdef:=tclassrefdef.create(resultdef);
                  end
                else

+ 3 - 2
compiler/nmem.pas

@@ -160,7 +160,8 @@ implementation
         case left.resultdef.typ of
           classrefdef :
             resultdef:=left.resultdef;
-          objectdef :
+          objectdef,
+          recorddef:
             { access to the classtype while specializing? }
             if (df_generic in left.resultdef.defoptions) then
               begin
@@ -202,7 +203,7 @@ implementation
              if is_objcclass(left.resultdef) and
                 (left.nodetype<>typen) then
                begin
-                 vs:=search_class_member(tobjectdef(left.resultdef),'ISA');
+                 vs:=search_struct_member(tobjectdef(left.resultdef),'ISA');
                  if not assigned(vs) or
                     (tsym(vs).typ<>fieldvarsym) then
                    internalerror(2009092502);

+ 2 - 2
compiler/nobj.pas

@@ -536,7 +536,7 @@ implementation
                 { Add procdef to the implemented interface }
                 if assigned(implprocdef) then
                   begin
-                    if (implprocdef._class.objecttype<>odt_objcclass) then
+                    if (tobjectdef(implprocdef.struct).objecttype<>odt_objcclass) then
                       ImplIntf.AddImplProc(implprocdef)
                     else
                       begin
@@ -1345,7 +1345,7 @@ implementation
           etVirtualMethodResult, etVirtualMethodClass:
             begin
               pd := tprocdef(tpropertysym(AImplIntf.ImplementsGetter).propaccesslist[palt_read].procdef);
-              current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(pd._class.vmtmethodoffset(pd.extnumber)));
+              current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(tobjectdef(pd.struct).vmtmethodoffset(pd.extnumber)));
             end;
           else
             internalerror(200802162);

+ 3 - 3
compiler/nutils.pas

@@ -534,9 +534,9 @@ implementation
         result:=internalstatements(newstatement);
 
         { call fail helper and exit normal }
-        if is_class(current_objectdef) then
+        if is_class(current_structdef) then
           begin
-            srsym:=search_class_member(current_objectdef,'FREEINSTANCE');
+            srsym:=search_struct_member(current_objectdef,'FREEINSTANCE');
             if assigned(srsym) and
                (srsym.typ=procsym) then
               begin
@@ -556,7 +556,7 @@ implementation
               internalerror(200305108);
           end
         else
-          if is_object(current_objectdef) then
+          if is_object(current_structdef) then
             begin
               { parameter 3 : vmt_offset }
               { parameter 2 : pointer to vmt }

+ 2 - 2
compiler/pdecl.pas

@@ -85,7 +85,7 @@ implementation
         if orgname='' then
          internalerror(9584582);
         hp:=nil;
-        p:=comp_expr(true);
+        p:=comp_expr(true,false);
         storetokenpos:=current_tokenpos;
         current_tokenpos:=filepos;
         case p.nodetype of
@@ -748,7 +748,7 @@ implementation
              _EQUAL:
                 begin
                    consume(_EQUAL);
-                   p:=comp_expr(true);
+                   p:=comp_expr(true,false);
                    storetokenpos:=current_tokenpos;
                    current_tokenpos:=filepos;
                    sym:=nil;

+ 7 - 7
compiler/pdecobj.pas

@@ -94,8 +94,8 @@ implementation
         include(current_objectdef.objectoptions,oo_has_constructor);
         { Set return type, class constructors return the
           created instance, object constructors return boolean }
-        if is_class(pd._class) then
-          pd.returndef:=pd._class
+        if is_class(pd.struct) then
+          pd.returndef:=pd.struct
         else
 {$ifdef CPU64bitaddr}
           pd.returndef:=bool64type;
@@ -314,7 +314,7 @@ implementation
         p : tnode;
         valid : boolean;
       begin
-        p:=comp_expr(true);
+        p:=comp_expr(true,false);
         if p.nodetype=stringconstn then
           begin
             stringdispose(current_objectdef.iidstr);
@@ -544,7 +544,7 @@ implementation
 
       procedure chkobjc(pd: tprocdef);
         begin
-          if is_objc_class_or_protocol(pd._class) then
+          if is_objc_class_or_protocol(pd.struct) then
             begin
               include(pd.procoptions,po_objc);
             end;
@@ -790,7 +790,7 @@ implementation
 
                 oldparse_only:=parse_only;
                 parse_only:=true;
-                pd:=parse_proc_dec(is_classdef, current_objectdef);
+                pd:=parse_proc_dec(is_classdef,current_objectdef);
 
                 { this is for error recovery as well as forward }
                 { interface mappings, i.e. mapping to a method  }
@@ -800,9 +800,9 @@ implementation
                     parse_object_proc_directives(pd);
 
                     { check if dispid is set }
-                    if is_dispinterface(pd._class) and not (po_dispid in pd.procoptions) then
+                    if is_dispinterface(pd.struct) and not (po_dispid in pd.procoptions) then
                       begin
-                        pd.dispid:=pd._class.get_next_dispid;
+                        pd.dispid:=tobjectdef(pd.struct).get_next_dispid;
                         include(pd.procoptions, po_dispid);
                       end;
 

+ 150 - 128
compiler/pdecsub.pas

@@ -31,13 +31,15 @@ interface
     type
       tpdflag=(
         pd_body,         { directive needs a body }
-        pd_implemen,     { directive can be used implementation section }
-        pd_interface,    { directive can be used interface section }
-        pd_object,       { directive can be used object declaration }
-        pd_procvar,      { directive can be used procvar declaration }
-        pd_notobject,    { directive can not be used object declaration }
-        pd_notobjintf,   { directive can not be used interface declaration }
-        pd_notprocvar,   { directive can not be used procvar declaration }
+        pd_implemen,     { directive can be used in implementation section }
+        pd_interface,    { directive can be used in interface section }
+        pd_object,       { directive can be used with object declaration }
+        pd_record,       { directive can be used with record declaration }
+        pd_procvar,      { directive can be used with procvar declaration }
+        pd_notobject,    { directive can not be used with object declaration }
+        pd_notrecord,    { directive can not be used with record declaration }
+        pd_notobjintf,   { directive can not be used with interface declaration }
+        pd_notprocvar,   { directive can not be used with procvar declaration }
         pd_dispinterface,{ directive can be used with dispinterface methods }
         pd_cppobject,    { directive can be used with cppclass }
         pd_objcclass,    { directive can be used with objcclass }
@@ -59,8 +61,9 @@ interface
     procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
     procedure parse_var_proc_directives(sym:tsym);
     procedure parse_object_proc_directives(pd:tabstractprocdef);
-    function  parse_proc_head(aclass:tobjectdef;potype:tproctypeoption;var pd:tprocdef):boolean;
-    function  parse_proc_dec(isclassmethod:boolean; aclass:tobjectdef):tprocdef;
+    procedure parse_record_proc_directives(pd:tabstractprocdef);
+    function  parse_proc_head(astruct:tabstractrecorddef;potype:tproctypeoption;var pd:tprocdef):boolean;
+    function  parse_proc_dec(isclassmethod:boolean;astruct:tabstractrecorddef):tprocdef;
 
     { helper functions - they insert nested objects hierarcy to the symtablestack
       with object hierarchy
@@ -246,7 +249,7 @@ implementation
         sl       : tpropaccesslist;
       begin
         if (pd.typ=procdef) and
-           is_objc_class_or_protocol(tprocdef(pd)._class) and
+           is_objc_class_or_protocol(tprocdef(pd).struct) and
            (pd.parast.symtablelevel=normal_function_level) then
           begin
             { insert Objective-C self and selector parameters }
@@ -263,7 +266,7 @@ implementation
               { compatible with what gcc does }
               hdef:=objc_idtype
             else
-              hdef:=tprocdef(pd)._class;
+              hdef:=tprocdef(pd).struct;
 
             vs:=tparavarsym.create('$self',paranr_objc_self,vs_value,hdef,[vo_is_self,vo_is_hidden_para]);
             pd.parast.insert(vs);
@@ -278,7 +281,7 @@ implementation
         else
           begin
              if (pd.typ=procdef) and
-                assigned(tprocdef(pd)._class) and
+                assigned(tprocdef(pd).struct) and
                 (pd.parast.symtablelevel=normal_function_level) then
               begin
                 { static class methods have no hidden self/vmt pointer }
@@ -289,7 +292,7 @@ implementation
                 current_tokenpos:=tprocdef(pd).fileinfo;
 
                 { Generate VMT variable for constructor/destructor }
-                if (pd.proctypeoption in [potype_constructor,potype_destructor]) and not(is_cppclass(tprocdef(pd)._class)) then
+                if (pd.proctypeoption in [potype_constructor,potype_destructor]) and not(is_cppclass(tprocdef(pd).struct)) then
                  begin
                    { can't use classrefdef as type because inheriting
                      will then always file because of a type mismatch }
@@ -303,12 +306,12 @@ implementation
                 vsp:=vs_value;
                 if (po_staticmethod in pd.procoptions) or
                    (po_classmethod in pd.procoptions) then
-                  hdef:=tclassrefdef.create(tprocdef(pd)._class)
+                  hdef:=tclassrefdef.create(tprocdef(pd).struct)
                 else
                   begin
-                    if is_object(tprocdef(pd)._class) then
+                    if is_object(tprocdef(pd).struct) or is_record(tprocdef(pd).struct) then
                       vsp:=vs_var;
-                    hdef:=tprocdef(pd)._class;
+                    hdef:=tprocdef(pd).struct;
                   end;
                 vs:=tparavarsym.create('$self',paranr_self,vsp,hdef,[vo_is_self,vo_is_hidden_para]);
                 pd.parast.insert(vs);
@@ -409,7 +412,7 @@ implementation
                     MessagePos(fileinfo,parser_w_cdecl_no_openstring);
                  if not(po_external in pd.procoptions) and
                     (pd.typ<>procvardef) and
-                    not is_objc_class_or_protocol(tprocdef(pd)._class) then
+                    not is_objc_class_or_protocol(tprocdef(pd).struct) then
                    if is_array_of_const(vardef) then
                      MessagePos(fileinfo,parser_e_varargs_need_cdecl_and_external)
                    else
@@ -732,7 +735,7 @@ implementation
             CGMessage(cg_e_file_must_call_by_reference);
 
           { Dispinterfaces are restricted to using only automatable types }
-          if (pd.typ=procdef) and is_dispinterface(tprocdef(pd)._class) and
+          if (pd.typ=procdef) and is_dispinterface(tprocdef(pd).struct) and
              not is_automatable(hdef) then
             Message1(type_e_not_automatable,hdef.typename);
 
@@ -784,7 +787,7 @@ implementation
       end;
 
 
-    function parse_proc_head(aclass:tobjectdef;potype:tproctypeoption;var pd:tprocdef):boolean;
+    function parse_proc_head(astruct:tabstractrecorddef;potype:tproctypeoption;var pd:tprocdef):boolean;
       var
         hs       : string;
         orgsp,sp : TIDString;
@@ -800,7 +803,7 @@ implementation
         popclass : integer;
         ImplIntf : TImplementedInterface;
         old_parse_generic : boolean;
-        old_current_objectdef,
+        old_current_structdef: tabstractrecorddef;
         old_current_genericdef,
         old_current_specializedef : tobjectdef;
       begin
@@ -825,9 +828,10 @@ implementation
           end;
 
         { examine interface map: function/procedure iname.functionname=locfuncname }
-        if assigned(aclass) and
-           assigned(aclass.ImplementedInterfaces) and
-           (aclass.ImplementedInterfaces.count>0) and
+        if assigned(astruct) and
+           (astruct.typ=objectdef) and
+           assigned(tobjectdef(astruct).ImplementedInterfaces) and
+           (tobjectdef(astruct).ImplementedInterfaces.count>0) and
            try_to_consume(_POINT) then
          begin
            storepos:=current_tokenpos;
@@ -844,7 +848,7 @@ implementation
            ImplIntf:=nil;
            if (srsym.typ=typesym) and
               (ttypesym(srsym).typedef.typ=objectdef) then
-             ImplIntf:=aclass.find_implemented_interface(tobjectdef(ttypesym(srsym).typedef));
+             ImplIntf:=tobjectdef(astruct).find_implemented_interface(tobjectdef(ttypesym(srsym).typedef));
            if ImplIntf=nil then
              Message(parser_e_interface_id_expected);
            consume(_ID);
@@ -860,14 +864,14 @@ implementation
          end;
 
         { method  ? }
-        if not assigned(aclass) and
+        if not assigned(astruct) and
            (potype<>potype_operator) and
            (symtablestack.top.symtablelevel=main_program_level) and
            try_to_consume(_POINT) then
          begin
            repeat
              searchagain:=false;
-             if not assigned(aclass) then
+             if not assigned(astruct) then
                begin
                  { search for object name }
                  storepos:=current_tokenpos;
@@ -887,19 +891,19 @@ implementation
              consume(_ID);
              { qualifier is class name ? }
              if (srsym.typ=typesym) and
-                (ttypesym(srsym).typedef.typ=objectdef) then
+                (ttypesym(srsym).typedef.typ in [objectdef,recorddef]) then
               begin
-                aclass:=tobjectdef(ttypesym(srsym).typedef);
+                astruct:=tabstractrecorddef(ttypesym(srsym).typedef);
                 if (token<>_POINT) and (potype in [potype_class_constructor,potype_class_destructor]) then
                   sp := lower(sp);
-                srsym:=tsym(aclass.symtable.Find(sp));
+                srsym:=tsym(astruct.symtable.Find(sp));
                 if assigned(srsym) then
                  begin
                    if srsym.typ=procsym then
                      aprocsym:=tprocsym(srsym)
                    else
                    if (srsym.typ=typesym) and
-                      (ttypesym(srsym).typedef.typ=objectdef) then
+                      (ttypesym(srsym).typedef.typ in [objectdef,recorddef]) then
                      begin
                        searchagain:=true;
                        consume(_POINT);
@@ -920,7 +924,7 @@ implementation
                  begin
                    Message(parser_e_methode_id_expected);
                    { recover by making it a normal procedure instead of method }
-                   aclass:=nil;
+                   astruct:=nil;
                  end;
               end
              else
@@ -1013,27 +1017,27 @@ implementation
             checkstack:=checkstack^.next;
           end;
         pd:=tprocdef.create(st.symtablelevel+1);
-        pd._class:=aclass;
+        pd.struct:=astruct;
         pd.procsym:=aprocsym;
         pd.proctypeoption:=potype;
 
         { methods inherit df_generic or df_specialization from the objectdef }
-        if assigned(pd._class) and
+        if assigned(pd.struct) and
            (pd.parast.symtablelevel=normal_function_level) then
           begin
-            if (df_generic in pd._class.defoptions) then
+            if (df_generic in pd.struct.defoptions) then
               begin
                 include(pd.defoptions,df_generic);
                 parse_generic:=true;
               end;
-            if (df_specialization in pd._class.defoptions) then
+            if (df_specialization in pd.struct.defoptions) then
               begin
                 include(pd.defoptions,df_specialization);
                 { Find corresponding genericdef, we need it later to
                   replay the tokens to generate the body }
-                if not assigned(pd._class.genericdef) then
+                if not assigned(pd.struct.genericdef) then
                   internalerror(200512113);
-                genericst:=pd._class.genericdef.GetSymtable(gs_record);
+                genericst:=pd.struct.genericdef.GetSymtable(gs_record);
                 if not assigned(genericst) then
                   internalerror(200512114);
                 { We are parsing the same objectdef, the def index numbers
@@ -1046,9 +1050,9 @@ implementation
           end;
 
         { methods need to be exported }
-        if assigned(aclass) and
+        if assigned(astruct) and
            (
-            (symtablestack.top.symtabletype=ObjectSymtable) or
+            (symtablestack.top.symtabletype in [ObjectSymtable,recordsymtable]) or
             (symtablestack.top.symtablelevel=main_program_level)
            ) then
           include(pd.procoptions,po_global);
@@ -1064,19 +1068,19 @@ implementation
           begin
             { Add ObjectSymtable to be able to find nested type definitions }
             popclass:=0;
-            if assigned(pd._class) and
+            if assigned(pd.struct) and
                (pd.parast.symtablelevel=normal_function_level) and
-               (symtablestack.top.symtabletype<>ObjectSymtable) then
+               not(symtablestack.top.symtabletype in [ObjectSymtable,recordsymtable]) then
               begin
-                popclass:=push_nested_hierarchy(pd._class);
-                old_current_objectdef:=current_objectdef;
+                popclass:=push_nested_hierarchy(pd.struct);
+                old_current_structdef:=current_structdef;
                 old_current_genericdef:=current_genericdef;
                 old_current_specializedef:=current_specializedef;
-                current_objectdef:=pd._class;
-                if assigned(current_objectdef) and (df_generic in current_objectdef.defoptions) then
-                  current_genericdef:=current_objectdef;
-                if assigned(current_objectdef) and (df_specialization in current_objectdef.defoptions) then
-                  current_specializedef:=current_objectdef;
+                current_structdef:=pd.struct;
+                if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
+                  current_genericdef:=tobjectdef(current_structdef);
+                if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
+                  current_specializedef:=tobjectdef(current_structdef);
               end;
             { Add parameter symtable }
             if pd.parast.symtabletype<>staticsymtable then
@@ -1086,10 +1090,10 @@ implementation
               symtablestack.pop(pd.parast);
             if popclass>0 then
               begin
-                current_objectdef:=old_current_objectdef;
+                current_structdef:=old_current_structdef;
                 current_genericdef:=old_current_genericdef;
                 current_specializedef:=old_current_specializedef;
-                dec(popclass,pop_nested_hierarchy(pd._class));
+                dec(popclass,pop_nested_hierarchy(pd.struct));
                 if popclass<>0 then
                   internalerror(201011260); // 11 nov 2010 index 0
               end;
@@ -1100,13 +1104,13 @@ implementation
       end;
 
 
-    function parse_proc_dec(isclassmethod:boolean; aclass:tobjectdef):tprocdef;
+    function parse_proc_dec(isclassmethod:boolean;astruct:tabstractrecorddef):tprocdef;
       var
         pd : tprocdef;
         locationstr: string;
         old_parse_generic: boolean;
         popclass: integer;
-        old_current_objectdef,
+        old_current_structdef: tabstractrecorddef;
         old_current_genericdef,
         old_current_specializedef: tobjectdef;
       begin
@@ -1116,7 +1120,7 @@ implementation
           _FUNCTION :
             begin
               consume(_FUNCTION);
-              if parse_proc_head(aclass,potype_function,pd) then
+              if parse_proc_head(astruct,potype_function,pd) then
                 begin
                   { pd=nil when it is a interface mapping }
                   if assigned(pd) then
@@ -1127,32 +1131,32 @@ implementation
                          inc(testcurobject);
                          { Add ObjectSymtable to be able to find generic type definitions }
                          popclass:=0;
-                         if assigned(pd._class) and
+                         if assigned(pd.struct) and
                             (pd.parast.symtablelevel=normal_function_level) and
-                            (symtablestack.top.symtabletype<>ObjectSymtable) then
+                            not (symtablestack.top.symtabletype in [ObjectSymtable,recordsymtable]) then
                            begin
-                             popclass:=push_nested_hierarchy(pd._class);
-                             parse_generic:=(df_generic in pd._class.defoptions);
-                             old_current_objectdef:=current_objectdef;
+                             popclass:=push_nested_hierarchy(pd.struct);
+                             parse_generic:=(df_generic in pd.struct.defoptions);
+                             old_current_structdef:=current_structdef;
                              old_current_genericdef:=current_genericdef;
                              old_current_specializedef:=current_specializedef;
-                             current_objectdef:=pd._class;
-                             if assigned(current_objectdef) and (df_generic in current_objectdef.defoptions) then
-                               current_genericdef:=current_objectdef;
-                             if assigned(current_objectdef) and (df_specialization in current_objectdef.defoptions) then
-                               current_specializedef:=current_objectdef;
+                             current_structdef:=pd.struct;
+                             if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
+                               current_genericdef:=tobjectdef(current_structdef);
+                             if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
+                               current_specializedef:=tobjectdef(current_structdef);
                            end;
                          single_type(pd.returndef,false,false);
 
-                         if is_dispinterface(pd._class) and not is_automatable(pd.returndef) then
+                         if is_dispinterface(pd.struct) and not is_automatable(pd.returndef) then
                            Message1(type_e_not_automatable,pd.returndef.typename);
 
                          if popclass>0 then
                            begin
-                             current_objectdef:=old_current_objectdef;
+                             current_structdef:=old_current_structdef;
                              current_genericdef:=old_current_genericdef;
                              current_specializedef:=old_current_specializedef;
-                             dec(popclass,pop_nested_hierarchy(pd._class));
+                             dec(popclass,pop_nested_hierarchy(pd.struct));
                              if popclass<>0 then
                                internalerror(201012020);
                            end;
@@ -1187,7 +1191,7 @@ implementation
                        begin
                           if (
                               parse_only and
-                              not(is_interface(pd._class))
+                              not(is_interface(pd.struct))
                              ) or
                              (m_repeat_forward in current_settings.modeswitches) then
                           begin
@@ -1210,7 +1214,7 @@ implementation
           _PROCEDURE :
             begin
               consume(_PROCEDURE);
-              if parse_proc_head(aclass,potype_procedure,pd) then
+              if parse_proc_head(astruct,potype_procedure,pd) then
                 begin
                   { pd=nil when it is an interface mapping }
                   if assigned(pd) then
@@ -1226,17 +1230,17 @@ implementation
             begin
               consume(_CONSTRUCTOR);
               if isclassmethod then
-                parse_proc_head(aclass,potype_class_constructor,pd)
+                parse_proc_head(astruct,potype_class_constructor,pd)
               else
-                parse_proc_head(aclass,potype_constructor,pd);
+                parse_proc_head(astruct,potype_constructor,pd);
               if not isclassmethod and
                  assigned(pd) and
-                 assigned(pd._class) then
+                 assigned(pd.struct) then
                 begin
                   { Set return type, class constructors return the
                     created instance, object constructors return boolean }
-                  if is_class(pd._class) then
-                    pd.returndef:=pd._class
+                  if is_class(pd.struct) then
+                    pd.returndef:=pd.struct
                   else
 {$ifdef CPU64bitaddr}
                     pd.returndef:=bool64type;
@@ -1252,9 +1256,9 @@ implementation
             begin
               consume(_DESTRUCTOR);
               if isclassmethod then
-                parse_proc_head(aclass,potype_class_destructor,pd)
+                parse_proc_head(astruct,potype_class_destructor,pd)
               else
-                parse_proc_head(aclass,potype_destructor,pd);
+                parse_proc_head(astruct,potype_destructor,pd);
               if assigned(pd) then
                 pd.returndef:=voidtype;
             end;
@@ -1286,7 +1290,7 @@ implementation
                  end;
                end;
               consume(token);
-              parse_proc_head(aclass,potype_operator,pd);
+              parse_proc_head(astruct,potype_operator,pd);
               if assigned(pd) then
                 begin
                   { operators always need to be searched in all units }
@@ -1375,7 +1379,7 @@ procedure pd_export(pd:tabstractprocdef);
 begin
   if pd.typ<>procdef then
     internalerror(200304264);
-  if assigned(tprocdef(pd)._class) then
+  if assigned(tprocdef(pd).struct) then
     Message(parser_e_methods_dont_be_export);
   if pd.parast.symtablelevel>normal_function_level then
     Message(parser_e_dont_nest_export);
@@ -1473,7 +1477,9 @@ procedure pd_abstract(pd:tabstractprocdef);
 begin
   if pd.typ<>procdef then
     internalerror(200304269);
-  if oo_is_sealed in tprocdef(pd)._class.objectoptions then
+  if assigned(tprocdef(pd).struct) and
+    (tprocdef(pd).struct.typ=objectdef) and
+    (oo_is_sealed in tobjectdef(tprocdef(pd).struct).objectoptions) then
     Message(parser_e_sealed_class_cannot_have_abstract_methods)
   else
   if (po_virtualmethod in pd.procoptions) then
@@ -1502,13 +1508,13 @@ begin
   begin
     if pattern='MOVENEXT' then
     begin
-      if oo_has_enumerator_movenext in tprocdef(pd)._class.objectoptions then
+      if oo_has_enumerator_movenext in tobjectdef(tprocdef(pd).struct).objectoptions then
         message(parser_e_only_one_enumerator_movenext);
       pd.calcparas;
       if (pd.proctypeoption = potype_function) and is_boolean(pd.returndef) and
          (pd.minparacount = 0) then
       begin
-        include(tprocdef(pd)._class.objectoptions, oo_has_enumerator_movenext);
+        include(tobjectdef(tprocdef(pd).struct).objectoptions, oo_has_enumerator_movenext);
         include(pd.procoptions,po_enumerator_movenext);
       end
       else
@@ -1531,10 +1537,10 @@ begin
   if pd.typ<>procdef then
     internalerror(2003042610);
   if (pd.proctypeoption=potype_constructor) and
-     is_object(tprocdef(pd)._class) then
+     is_object(tprocdef(pd).struct) then
     Message(parser_e_constructor_cannot_be_not_virtual);
 {$ifdef WITHDMT}
-  if is_object(tprocdef(pd)._class) and
+  if is_object(tprocdef(pd).struct) and
      (token<>_SEMICOLON) then
     begin
        { any type of parameter is allowed here! }
@@ -1559,7 +1565,7 @@ var pt:Tnode;
 begin
   if pd.typ<>procdef then
     internalerror(200604301);
-  pt:=comp_expr(true);
+  pt:=comp_expr(true,false);
   if is_constintnode(pt) then
     if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
       message(parser_e_range_check_error)
@@ -1582,9 +1588,9 @@ procedure pd_override(pd:tabstractprocdef);
 begin
   if pd.typ<>procdef then
     internalerror(2003042611);
-  if not(is_class_or_interface_or_objc(tprocdef(pd)._class)) then
+  if not(is_class_or_interface_or_objc(tprocdef(pd).struct)) then
     Message(parser_e_no_object_override)
-  else if is_objccategory(tprocdef(pd)._class) then
+  else if is_objccategory(tprocdef(pd).struct) then
     Message(parser_e_no_category_override);
 end;
 
@@ -1602,20 +1608,20 @@ var
 begin
   if pd.typ<>procdef then
     internalerror(2003042613);
-  if not is_class(tprocdef(pd)._class) and
-     not is_objc_class_or_protocol(tprocdef(pd)._class) then
+  if not is_class(tprocdef(pd).struct) and
+     not is_objc_class_or_protocol(tprocdef(pd).struct) then
     Message(parser_e_msg_only_for_classes);
   if ([po_msgstr,po_msgint]*pd.procoptions)<>[] then
     Message(parser_e_multiple_messages);
   { check parameter type }
-  if not is_objc_class_or_protocol(tprocdef(pd)._class) then
+  if not is_objc_class_or_protocol(tprocdef(pd).struct) then
     begin
       paracnt:=0;
       pd.parast.SymList.ForEachCall(@check_msg_para,@paracnt);
       if paracnt<>1 then
         Message(parser_e_ill_msg_param);
     end;
-  pt:=comp_expr(true);
+  pt:=comp_expr(true,false);
   { message is 1-character long }
   if is_constcharnode(pt) then
     begin
@@ -1631,7 +1637,7 @@ begin
     end
   else
    if is_constintnode(pt) and
-      is_class(tprocdef(pd)._class) then
+      is_class(tprocdef(pd).struct) then
     begin
       include(pd.procoptions,po_msgint);
       if (Tordconstnode(pt).value<int64(low(Tprocdef(pd).messageinf.i))) or
@@ -1644,7 +1650,7 @@ begin
     Message(parser_e_ill_msg_expr);
   { check whether the selector name is valid in case of Objective-C }
   if (po_msgstr in pd.procoptions) and
-     is_objc_class_or_protocol(tprocdef(pd)._class) and
+     is_objc_class_or_protocol(tprocdef(pd).struct) and
      not objcvalidselectorname(@tprocdef(pd).messageinf.str^[1],length(tprocdef(pd).messageinf.str^)) then
     Message1(type_e_invalid_objc_selector_name,tprocdef(pd).messageinf.str^);
   pt.free;
@@ -1655,8 +1661,8 @@ procedure pd_reintroduce(pd:tabstractprocdef);
 begin
   if pd.typ<>procdef then
     internalerror(200401211);
-  if not(is_class_or_interface_or_object(tprocdef(pd)._class)) and
-     not(is_objccategory(tprocdef(pd)._class)) then
+  if not(is_class_or_interface_or_object(tprocdef(pd).struct)) and
+     not(is_objccategory(tprocdef(pd).struct)) then
     Message(parser_e_no_object_reintroduce);
 end;
 
@@ -1937,7 +1943,7 @@ const
    (
     (
       idtok:_ABSTRACT;
-      pd_flags : [pd_interface,pd_object,pd_notobjintf];
+      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord];
       handler  : @pd_abstract;
       pocall   : pocall_none;
       pooption : [po_abstractmethod];
@@ -2000,7 +2006,7 @@ const
       mutexclpo     : [po_interrupt,po_external,po_inline]
     ),(
       idtok:_DYNAMIC;
-      pd_flags : [pd_interface,pd_object,pd_notobjintf];
+      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord];
       handler  : @pd_virtual;
       pocall   : pocall_none;
       pooption : [po_virtualmethod];
@@ -2009,7 +2015,7 @@ const
       mutexclpo     : [po_exports,po_interrupt,po_external,po_overridingmethod,po_inline]
     ),(
       idtok:_EXPORT;
-      pd_flags : [pd_body,pd_interface,pd_implemen,pd_notobjintf];
+      pd_flags : [pd_body,pd_interface,pd_implemen,pd_notobjintf,pd_notrecord];
       handler  : @pd_export;
       pocall   : pocall_none;
       pooption : [po_exports,po_global];
@@ -2018,7 +2024,7 @@ const
       mutexclpo     : [po_external,po_interrupt,po_inline]
     ),(
       idtok:_EXTERNAL;
-      pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf,pd_cppobject];
+      pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf,pd_cppobject,pd_notrecord];
       handler  : @pd_external;
       pocall   : pocall_none;
       pooption : [po_external];
@@ -2028,7 +2034,7 @@ const
       mutexclpo     : [po_public,po_exports,po_interrupt,po_assembler,po_inline]
     ),(
       idtok:_FAR;
-      pd_flags : [pd_implemen,pd_body,pd_interface,pd_procvar,pd_notobject,pd_notobjintf];
+      pd_flags : [pd_implemen,pd_body,pd_interface,pd_procvar,pd_notobject,pd_notobjintf,pd_notrecord];
       handler  : @pd_far;
       pocall   : pocall_none;
       pooption : [];
@@ -2037,7 +2043,7 @@ const
       mutexclpo     : [po_inline]
     ),(
       idtok:_FAR16;
-      pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar,pd_notobject];
+      pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar,pd_notobject,pd_notrecord];
       handler  : nil;
       pocall   : pocall_far16;
       pooption : [];
@@ -2046,7 +2052,7 @@ const
       mutexclpo     : [po_external]
     ),(
       idtok:_FINAL;
-      pd_flags : [pd_interface,pd_object,pd_notobjintf];
+      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord];
       handler  : @pd_final;
       pocall   : pocall_none;
       pooption : [po_finalmethod];
@@ -2055,7 +2061,7 @@ const
       mutexclpo     : [po_exports,po_interrupt,po_external,po_inline]
     ),(
       idtok:_FORWARD;
-      pd_flags : [pd_implemen,pd_notobject,pd_notobjintf];
+      pd_flags : [pd_implemen,pd_notobject,pd_notobjintf,pd_notrecord];
       handler  : @pd_forward;
       pocall   : pocall_none;
       pooption : [];
@@ -2082,7 +2088,7 @@ const
       mutexclpo     : [po_exports,po_external,po_interrupt,po_virtualmethod]
     ),(
       idtok:_INTERNCONST;
-      pd_flags : [pd_interface,pd_body,pd_notobject,pd_notobjintf];
+      pd_flags : [pd_interface,pd_body,pd_notobject,pd_notobjintf,pd_notrecord];
       handler  : @pd_internconst;
       pocall   : pocall_none;
       pooption : [po_internconst];
@@ -2091,7 +2097,7 @@ const
       mutexclpo     : []
     ),(
       idtok:_INTERNPROC;
-      pd_flags : [pd_interface,pd_notobject,pd_notobjintf];
+      pd_flags : [pd_interface,pd_notobject,pd_notobjintf,pd_notrecord];
       handler  : @pd_internproc;
       pocall   : pocall_internproc;
       pooption : [];
@@ -2100,7 +2106,7 @@ const
       mutexclpo     : [po_exports,po_external,po_interrupt,po_assembler,po_iocheck,po_virtualmethod]
     ),(
       idtok:_INTERRUPT;
-      pd_flags : [pd_implemen,pd_body,pd_notobject,pd_notobjintf];
+      pd_flags : [pd_implemen,pd_body,pd_notobject,pd_notobjintf,pd_notrecord];
       handler  : @pd_interrupt;
       pocall   : pocall_oldfpccall;
       pooption : [po_interrupt];
@@ -2128,7 +2134,7 @@ const
       mutexclpo     : [po_external,po_exports]
     ),(
       idtok:_MESSAGE;
-      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass, pd_objcprot];
+      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass,pd_objcprot,pd_notrecord];
       handler  : @pd_message;
       pocall   : pocall_none;
       pooption : []; { can be po_msgstr or po_msgint }
@@ -2146,7 +2152,7 @@ const
       mutexclpo     : []
     ),(
       idtok:_NEAR;
-      pd_flags : [pd_implemen,pd_body,pd_procvar,pd_notobjintf];
+      pd_flags : [pd_implemen,pd_body,pd_procvar,pd_notobjintf,pd_notrecord];
       handler  : @pd_near;
       pocall   : pocall_none;
       pooption : [];
@@ -2173,7 +2179,7 @@ const
       mutexclpo     : []
     ),(
       idtok:_OVERRIDE;
-      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass];
+      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass,pd_notrecord];
       handler  : @pd_override;
       pocall   : pocall_none;
       pooption : [po_overridingmethod,po_virtualmethod];
@@ -2191,7 +2197,7 @@ const
       mutexclpo     : [po_external]
     ),(
       idtok:_PUBLIC;
-      pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobject,pd_notobjintf];
+      pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobject,pd_notobjintf,pd_notrecord];
       handler  : @pd_public;
       pocall   : pocall_none;
       pooption : [po_public,po_global];
@@ -2209,7 +2215,7 @@ const
       mutexclpo     : [po_external]
     ),(
       idtok:_REINTRODUCE;
-      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass];
+      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass,pd_notrecord];
       handler  : @pd_reintroduce;
       pocall   : pocall_none;
       pooption : [po_reintroduce];
@@ -2238,7 +2244,7 @@ const
       mutexclpo     : []
     ),(
       idtok:_STATIC;
-      pd_flags : [pd_interface,pd_implemen,pd_body,pd_object,pd_notobjintf];
+      pd_flags : [pd_interface,pd_implemen,pd_body,pd_object,pd_record,pd_notobjintf];
       handler  : @pd_static;
       pocall   : pocall_none;
       pooption : [po_staticmethod];
@@ -2268,7 +2274,7 @@ const
       mutexclpo     : [po_external,po_assembler,po_interrupt,po_exports]
     ),(
       idtok:_VIRTUAL;
-      pd_flags : [pd_interface,pd_object,pd_notobjintf];
+      pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord];
       handler  : @pd_virtual;
       pocall   : pocall_none;
       pooption : [po_virtualmethod];
@@ -2286,7 +2292,7 @@ const
       mutexclpo     : [po_assembler,po_external,po_virtualmethod]
     ),(
       idtok:_VARARGS;
-      pd_flags : [pd_interface,pd_implemen,pd_procvar,pd_objcclass, pd_objcprot];
+      pd_flags : [pd_interface,pd_implemen,pd_procvar,pd_objcclass,pd_objcprot];
       handler  : nil;
       pocall   : pocall_none;
       pooption : [po_varargs];
@@ -2305,7 +2311,7 @@ const
       mutexclpo     : [po_interrupt]
     ),(
       idtok:_WEAKEXTERNAL;
-      pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf,pd_cppobject];
+      pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf,pd_cppobject,pd_notrecord];
       handler  : @pd_weakexternal;
       pocall   : pocall_none;
       { mark it both external and weak external, so we don't have to
@@ -2392,7 +2398,7 @@ const
          begin
             { parsing a procvar type the name can be any
               next variable !! }
-            if ((pdflags * [pd_procvar,pd_object,pd_objcclass,pd_objcprot])=[]) and
+            if ((pdflags * [pd_procvar,pd_object,pd_record,pd_objcclass,pd_objcprot])=[]) and
                not(idtoken=_PROPERTY) then
               Message1(parser_w_unknown_proc_directive_ignored,name);
             exit;
@@ -2406,6 +2412,10 @@ const
            not(is_cppclass(tdef(symtablestack.top.defowner)) and (pd_cppobject in proc_direcdata[p].pd_flags)) then
            exit;
 
+        if (pd_notrecord in proc_direcdata[p].pd_flags) and
+           (symtablestack.top.symtabletype=recordsymtable) then
+           exit;
+
         { Conflicts between directives ? }
         if (pd.proctypeoption in proc_direcdata[p].mutexclpotype) or
            (pd.proccalloption in proc_direcdata[p].mutexclpocall) or
@@ -2439,26 +2449,31 @@ const
          begin
            { Check if the directive is only for objects }
            if (pd_object in proc_direcdata[p].pd_flags) and
-              not assigned(tprocdef(pd)._class) then
+              not assigned(tprocdef(pd).struct) then
+            exit;
+
+           { Check if the directive is only for records }
+           if (pd_record in proc_direcdata[p].pd_flags) and
+              not assigned(tprocdef(pd).struct) then
             exit;
 
            { check if method and directive not for interface }
            if (pd_notobjintf in proc_direcdata[p].pd_flags) and
-              is_interface(tprocdef(pd)._class) then
+              is_interface(tprocdef(pd).struct) then
             exit;
 
            { check if method and directive not for interface }
-           if is_dispinterface(tprocdef(pd)._class) and
+           if is_dispinterface(tprocdef(pd).struct) and
              not(pd_dispinterface in proc_direcdata[p].pd_flags) then
             exit;
 
            { check if method and directive not for objcclass }
-           if is_objcclass(tprocdef(pd)._class) and
+           if is_objcclass(tprocdef(pd).struct) and
              not(pd_objcclass in proc_direcdata[p].pd_flags) then
             exit;
 
            { check if method and directive not for objcprotocol }
-           if is_objcprotocol(tprocdef(pd)._class) and
+           if is_objcprotocol(tprocdef(pd).struct) and
              not(pd_objcprot in proc_direcdata[p].pd_flags) then
             exit;
 
@@ -2557,8 +2572,8 @@ const
             case pd.proccalloption of
               pocall_cdecl :
                 begin
-                  if assigned(pd._class) then
-                    result:=target_info.Cprefix+pd._class.objrealname^+'_'+pd.procsym.realname
+                  if assigned(pd.struct) then
+                    result:=target_info.Cprefix+pd.struct.objrealname^+'_'+pd.procsym.realname
                   else
                     result:=target_info.Cprefix+pd.procsym.realname;
                 end;
@@ -2628,8 +2643,8 @@ const
             case pd.proccalloption of
               pocall_cdecl :
                 begin
-                  if assigned(pd._class) then
-                   pd.aliasnames.insert(target_info.Cprefix+pd._class.objrealname^+'_'+pd.procsym.realname)
+                  if assigned(pd.struct) then
+                   pd.aliasnames.insert(target_info.Cprefix+pd.struct.objrealname^+'_'+pd.procsym.realname)
                   else
                     begin
                       { Export names are not mangled on Windows and OS/2, see also pexports.pas }
@@ -2655,13 +2670,13 @@ const
       begin
         { set the default calling convention if none provided }
         if (pd.typ=procdef) and
-           (is_objc_class_or_protocol(tprocdef(pd)._class) or
-            is_cppclass(tprocdef(pd)._class)) then
+           (is_objc_class_or_protocol(tprocdef(pd).struct) or
+            is_cppclass(tprocdef(pd).struct)) then
           begin
             { none of the explicit calling conventions should be allowed }
             if (po_hascallingconvention in pd.procoptions) then
               internalerror(2009032501);
-            if is_cppclass(tprocdef(pd)._class) then
+            if is_cppclass(tprocdef(pd).struct) then
               pd.proccalloption:=pocall_cppdecl
             else
               pd.proccalloption:=pocall_cdecl;
@@ -2716,7 +2731,7 @@ const
                      (pd.typ=procvardef) or
                      { for objcclasses this is checked later, because the entire
                        class may be external.  }
-                     is_objc_class_or_protocol(tprocdef(pd)._class)) and
+                     is_objc_class_or_protocol(tprocdef(pd).struct)) and
                  not(pd.proccalloption in (cdecl_pocalls + [pocall_mwpascal])) then
                 Message(parser_e_varargs_need_cdecl_and_external);
             end
@@ -2862,6 +2877,13 @@ const
         parse_proc_directives(pd,pdflags);
       end;
 
+    procedure parse_record_proc_directives(pd:tabstractprocdef);
+      var
+        pdflags : tpdflags;
+      begin
+        pdflags:=[pd_record];
+        parse_proc_directives(pd,pdflags);
+      end;
 
     function proc_add_definition(var currpd:tprocdef):boolean;
       {
@@ -3141,7 +3163,7 @@ const
                  { check if all procs have overloading, but not if the proc is a method or
                    already declared forward, then the check is already done }
                  if not(fwpd.hasforward or
-                        assigned(currpd._class) or
+                        assigned(currpd.struct) or
                         (currpd.forwarddef<>fwpd.forwarddef) or
                         ((po_overload in currpd.procoptions) and
                          (po_overload in fwpd.procoptions))) then

+ 13 - 12
compiler/pdecvar.pas

@@ -83,7 +83,7 @@ implementation
             if token=_ID then
              begin
                if assigned(aclass) then
-                 sym:=search_class_member(aclass,pattern)
+                 sym:=search_struct_member(aclass,pattern)
                else
                  searchsym(pattern,sym,srsymtable);
                if assigned(sym) then
@@ -137,7 +137,7 @@ implementation
                            begin
                              sym:=tsym(st.Find(pattern));
                              if not(assigned(sym)) and is_object(def) then
-                               sym:=search_class_member(tobjectdef(def),pattern);
+                               sym:=search_struct_member(tobjectdef(def),pattern);
                              if assigned(sym) then
                               begin
                                 pl.addsym(sl_subscript,sym);
@@ -177,7 +177,7 @@ implementation
                          if def.typ=arraydef then
                           begin
                             idx:=0;
-                            p:=comp_expr(true);
+                            p:=comp_expr(true,false);
                             if (not codegenerror) then
                              begin
                                if (p.nodetype=ordconstn) then
@@ -268,7 +268,7 @@ implementation
 
               if try_to_consume(_DISPID) then
                 begin
-                  pt:=comp_expr(true);
+                  pt:=comp_expr(true,false);
                   if is_constintnode(pt) then
                     if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
                       message(parser_e_range_check_error)
@@ -427,7 +427,7 @@ implementation
               if (idtoken=_INDEX) then
                 begin
                    consume(_INDEX);
-                   pt:=comp_expr(true);
+                   pt:=comp_expr(true,false);
                    { Only allow enum and integer indexes. Convert all integer
                      values to s32int to be compatible with delphi, because the
                      procedure matching requires equal parameters }
@@ -457,7 +457,7 @@ implementation
          else
            begin
               { do an property override }
-              overridden:=search_class_member(aclass.childof,p.name);
+              overridden:=search_struct_member(aclass.childof,p.name);
               if assigned(overridden) and
                  (overridden.typ=propertysym) and
                  not(is_dispinterface(aclass)) then
@@ -618,7 +618,7 @@ implementation
                            methods
                          }
                          if (not assigned(aclass) or
-                             (search_class_member(aclass,pattern)=nil)) and
+                             (search_struct_member(aclass,pattern)=nil)) and
                             searchsym(pattern,sym,srsymtable) and
                             (sym.typ = constsym) then
                            begin
@@ -678,14 +678,14 @@ implementation
                 begin
                   Message(parser_e_property_cant_have_a_default_value);
                   { Error recovery }
-                  pt:=comp_expr(true);
+                  pt:=comp_expr(true,false);
                   pt.free;
                 end
               else
                 begin
                   { Get the result of the default, the firstpass is
                     needed to support values like -1 }
-                  pt:=comp_expr(true);
+                  pt:=comp_expr(true,false);
                   if (p.propdef.typ=setdef) and
                      (pt.nodetype=arrayconstructorn) then
                     begin
@@ -1428,7 +1428,8 @@ implementation
              { Don't search in the recordsymtable for types (can be nested!) }
              recstlist.count:=0;
              if ([df_generic,df_specialization]*tdef(recst.defowner).defoptions=[]) and
-                 not is_class_or_object(tdef(recst.defowner)) then
+                 not is_class_or_object(tdef(recst.defowner)) and
+                 not is_record(tdef(recst.defowner)) then
                begin
                  recstlist.add(recst);
                  symtablestack.pop(recst);
@@ -1619,11 +1620,11 @@ implementation
               symtablestack.push(UnionSymtable);
               repeat
                 repeat
-                  pt:=comp_expr(true);
+                  pt:=comp_expr(true,false);
                   if not(pt.nodetype=ordconstn) then
                     Message(parser_e_illegal_expression);
                   if try_to_consume(_POINTPOINT) then
-                    pt:=crangenode.create(pt,comp_expr(true));
+                    pt:=crangenode.create(pt,comp_expr(true,false));
                   pt.free;
                   if token=_COMMA then
                     consume(_COMMA)

+ 2 - 2
compiler/pexports.pas

@@ -136,7 +136,7 @@ implementation
                      end;
                     if try_to_consume(_INDEX) then
                      begin
-                       pt:=comp_expr(true);
+                       pt:=comp_expr(true,false);
                        if pt.nodetype=ordconstn then
                         if (Tordconstnode(pt).value<int64(low(index))) or
                            (Tordconstnode(pt).value>int64(high(index))) then
@@ -160,7 +160,7 @@ implementation
                      end;
                     if try_to_consume(_NAME) then
                      begin
-                       pt:=comp_expr(true);
+                       pt:=comp_expr(true,false);
                        if pt.nodetype=stringconstn then
                          hpname:=strpas(tstringconstnode(pt).value_str)
                        else

+ 119 - 119
compiler/pexpr.pas

@@ -31,13 +31,13 @@ interface
       tokens,globtype,globals,constexp;
 
     { reads a whole expression }
-    function expr(dotypecheck : boolean) : tnode;
+    function expr(dotypecheck:boolean) : tnode;
 
     { reads an expression without assignements and .. }
-    function comp_expr(accept_equal : boolean):tnode;
+    function comp_expr(accept_equal,typeonly:boolean):tnode;
 
     { reads a single factor }
-    function factor(getaddr : boolean) : tnode;
+    function factor(getaddr,typeonly:boolean) : tnode;
 
     procedure string_dec(var def: tdef; allowtypedef: boolean);
 
@@ -79,7 +79,7 @@ implementation
     const
       highest_precedence = oppower;
 
-    function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):tnode;forward;
+    function sub_expr(pred_level:Toperator_precedence;accept_equal,typeonly:boolean):tnode;forward;
 
     const
        { true, if the inherited call is anonymous }
@@ -101,7 +101,7 @@ implementation
               if not(allowtypedef) then
                 Message(parser_e_no_local_para_def);
               consume(_LECKKLAMMER);
-              p:=comp_expr(true);
+              p:=comp_expr(true,false);
               if not is_constintnode(p) then
                 begin
                   Message(parser_e_illegal_expression);
@@ -172,12 +172,12 @@ implementation
                else
                  begin
                    named_args_allowed:=true;
-                   p1:=comp_expr(true);
+                   p1:=comp_expr(true,false);
                    named_args_allowed:=false;
                    if found_arg_name then
                      begin
                        argname:=p1;
-                       p1:=comp_expr(true);
+                       p1:=comp_expr(true,false);
                        p2:=ccallparanode.create(p1,p2);
                        tcallparanode(p2).parametername:=argname;
                      end
@@ -188,19 +188,19 @@ implementation
              end
            else
              begin
-               p1:=comp_expr(true);
+               p1:=comp_expr(true,false);
                p2:=ccallparanode.create(p1,p2);
              end;
            { it's for the str(l:5,s); }
            if __colon and (token=_COLON) then
              begin
                consume(_COLON);
-               p1:=comp_expr(true);
+               p1:=comp_expr(true,false);
                p2:=ccallparanode.create(p1,p2);
                include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
                if try_to_consume(_COLON) then
                  begin
-                   p1:=comp_expr(true);
+                   p1:=comp_expr(true,false);
                    p2:=ccallparanode.create(p1,p2);
                    include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
                  end
@@ -282,7 +282,7 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               consume(_RKLAMMER);
               p1:=geninlinenode(in_ord_x,false,p1);
               statement_syssym := p1;
@@ -296,7 +296,7 @@ implementation
                     begin
                       if not(try_to_consume(_RKLAMMER)) then
                         begin
-                          p1:=comp_expr(true);
+                          p1:=comp_expr(true,false);
                           consume(_RKLAMMER);
                           if (not assigned(current_procinfo) or
                               is_void(current_procinfo.procdef.returndef)) then
@@ -360,7 +360,7 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               consume(_RKLAMMER);
               if p1.nodetype=typen then
                 ttypenode(p1).allowed:=true;
@@ -386,7 +386,7 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               consume(_RKLAMMER);
               if (p1.nodetype<>typen) and
                  (
@@ -431,7 +431,7 @@ implementation
                 begin
                   consume(_LKLAMMER);
                   in_args:=true;
-                  p1:=comp_expr(true);
+                  p1:=comp_expr(true,false);
                   { When reading a class type it is parsed as loadvmtaddrn,
                     typeinfo only needs the type so we remove the loadvmtaddrn }
                   if p1.nodetype=loadvmtaddrn then
@@ -465,7 +465,7 @@ implementation
               err:=false;
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               p2:=ccallparanode.create(p1,nil);
               p2:=geninlinenode(in_unaligned_x,false,p2);
               consume(_RKLAMMER);
@@ -477,7 +477,7 @@ implementation
               err:=false;
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               { When reading a class type it is parsed as loadvmtaddrn,
                 typeinfo only needs the type so we remove the loadvmtaddrn }
               if p1.nodetype=loadvmtaddrn then
@@ -533,7 +533,7 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               p1:=caddrnode.create(p1);
               if cs_typed_addresses in current_settings.localswitches then
                 include(p1.flags,nf_typedaddr);
@@ -545,7 +545,7 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               p1:=caddrnode.create(p1);
               do_typecheckpass(p1);
               { Ofs() returns a cardinal/qword, not a pointer }
@@ -558,7 +558,7 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               p1:=geninlinenode(in_seg_x,false,p1);
               consume(_RKLAMMER);
               statement_syssym:=p1;
@@ -569,7 +569,7 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               p2:=geninlinenode(l,false,p1);
               consume(_RKLAMMER);
               statement_syssym:=p2;
@@ -580,7 +580,7 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               p2:=geninlinenode(l,false,p1);
               consume(_RKLAMMER);
               statement_syssym:=p2;
@@ -591,9 +591,9 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               if try_to_consume(_COMMA) then
-                p2:=ccallparanode.create(comp_expr(true),nil)
+                p2:=ccallparanode.create(comp_expr(true,false),nil)
               else
                 p2:=nil;
               p2:=ccallparanode.create(p1,p2);
@@ -608,9 +608,9 @@ implementation
                   message(parser_e_illegal_slice);
                   consume(_LKLAMMER);
                   in_args:=true;
-                  comp_expr(true).free;
+                  comp_expr(true,false).free;
                   if try_to_consume(_COMMA) then
-                    comp_expr(true).free;
+                    comp_expr(true,false).free;
                   statement_syssym:=cerrornode.create;
                   consume(_RKLAMMER);
                 end
@@ -618,10 +618,10 @@ implementation
                 begin
                   consume(_LKLAMMER);
                   in_args:=true;
-                  p1:=comp_expr(true);
+                  p1:=comp_expr(true,false);
                   Consume(_COMMA);
                   if not(codegenerror) then
-                    p2:=ccallparanode.create(comp_expr(true),nil)
+                    p2:=ccallparanode.create(comp_expr(true,false),nil)
                   else
                     p2:=cerrornode.create;
                   p2:=ccallparanode.create(p1,p2);
@@ -653,7 +653,7 @@ implementation
                 type checking }
               p2:=nil;
               repeat
-                p1:=comp_expr(true);
+                p1:=comp_expr(true,false);
                 if p2<>nil then
                   p2:=caddnode.create(addn,p2,p1)
                 else
@@ -699,7 +699,7 @@ implementation
                   consume(_LKLAMMER);
                   in_args:=true;
                   { don't turn procsyms into calls (getaddr = true) }
-                  p1:=factor(true);
+                  p1:=factor(true,false);
                   p2:=geninlinenode(l,false,p1);
                   consume(_RKLAMMER);
                   statement_syssym:=p2;
@@ -714,7 +714,7 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               p2:=geninlinenode(l,false,p1);
               consume(_RKLAMMER);
               statement_syssym:=p2;
@@ -748,11 +748,11 @@ implementation
             Begin
               consume(_LKLAMMER);
               in_args := true;
-              p1:= ccallparanode.create(comp_expr(true), nil);
+              p1:= ccallparanode.create(comp_expr(true,false), nil);
               consume(_COMMA);
-              p2 := ccallparanode.create(comp_expr(true),p1);
+              p2 := ccallparanode.create(comp_expr(true,false),p1);
               if try_to_consume(_COMMA) then
-                p2 := ccallparanode.create(comp_expr(true),p2);
+                p2 := ccallparanode.create(comp_expr(true,false),p2);
               consume(_RKLAMMER);
               p2 := geninlinenode(l,false,p2);
               statement_syssym := p2;
@@ -763,9 +763,9 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               consume(_COMMA);
-              p2:=comp_expr(true);
+              p2:=comp_expr(true,false);
               statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,nil)));
               consume(_RKLAMMER);
             end;
@@ -775,11 +775,11 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               consume(_COMMA);
-              p2:=comp_expr(true);
+              p2:=comp_expr(true,false);
               consume(_COMMA);
-              paras:=comp_expr(true);
+              paras:=comp_expr(true,false);
               statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,ccallparanode.create(paras,nil))));
               consume(_RKLAMMER);
             end;
@@ -788,9 +788,9 @@ implementation
             begin
               consume(_LKLAMMER);
               in_args:=true;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               if try_to_consume(_COMMA) then
-                 p2:=comp_expr(true)
+                 p2:=comp_expr(true,false)
               else
                begin
                  { then insert an empty string }
@@ -812,7 +812,7 @@ implementation
                    however, as a stack frame may not exist, it does more harm than
                    good, so ignore it.}
                   in_args:=true;
-                  p1:=comp_expr(true);
+                  p1:=comp_expr(true,false);
                   p1.destroy;
                   consume(_RKLAMMER);
                 end;
@@ -838,11 +838,12 @@ implementation
                  if (st.defowner.typ=objectdef) then
                    p1:=tnode(twithsymtable(st).withrefnode).getcopy;
                end;
-             ObjectSymtable :
+             ObjectSymtable,
+             recordsymtable:
                begin
                  { We are calling from the static class method which has no self node }
                  if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
-                   p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef._class))
+                   p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef.struct))
                  else
                    p1:=load_self_node;
                  { We are calling a member }
@@ -1068,7 +1069,7 @@ implementation
                          { read the expression }
                          if propsym.propdef.typ=procvardef then
                            getprocvardef:=tprocvardef(propsym.propdef);
-                         p2:=comp_expr(true);
+                         p2:=comp_expr(true,false);
                          if assigned(getprocvardef) then
                            handle_procvar(getprocvardef,p2);
                          tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
@@ -1095,7 +1096,7 @@ implementation
                          include(p1.flags,nf_isproperty);
                          consume(_ASSIGNMENT);
                          { read the expression }
-                         p2:=comp_expr(true);
+                         p2:=comp_expr(true,false);
                          p1:=cassignmentnode.create(p1,p2);
                       end
                     else
@@ -1109,7 +1110,7 @@ implementation
               if (ppo_dispid_write in propsym.propoptions) then
                 begin
                   consume(_ASSIGNMENT);
-                  p2:=comp_expr(true);
+                  p2:=comp_expr(true,false);
                   { concat value parameter too }
                   p2:=ccallparanode.create(p2,nil);
                   { passing p3 here is only for information purposes }
@@ -1255,7 +1256,7 @@ implementation
                               (
                                 is_self_node(p1) or
                                 (assigned(current_procinfo) and (current_procinfo.procdef.no_self_node) and
-                                 (current_procinfo.procdef._class = structh))) then
+                                (current_procinfo.procdef.struct=structh))) then
                               Message(parser_e_only_class_members)
                             else
                               Message(parser_e_only_class_members_via_class_ref);
@@ -1273,7 +1274,7 @@ implementation
                      p1.free;
                      if try_to_consume(_LKLAMMER) then
                       begin
-                        p1:=comp_expr(true);
+                        p1:=comp_expr(true,false);
                         consume(_RKLAMMER);
                         p1:=ctypeconvnode.create_explicit(p1,ttypesym(sym).typedef);
                       end
@@ -1317,7 +1318,8 @@ implementation
         memberparentdef:=nil;
 
         case st.symtabletype of
-          ObjectSymtable:
+          ObjectSymtable,
+          recordsymtable:
             begin
               memberparentdef:=tdef(st.defowner);
               exit;
@@ -1344,7 +1346,7 @@ implementation
 
   {$maxfpuregisters 0}
 
-    function factor(getaddr : boolean) : tnode;
+    function factor(getaddr,typeonly:boolean) : tnode;
 
          {---------------------------------------------
                          Factor_read_id
@@ -1373,7 +1375,10 @@ implementation
              end
            else
              begin
-               searchsym(pattern,srsym,srsymtable);
+               if typeonly then
+                 searchsym_type(pattern,srsym,srsymtable)
+               else
+                 searchsym(pattern,srsym,srsymtable);
 
                { handle unit specification like System.Writeln }
                unit_found:=try_consume_unitsym(srsym,srsymtable,t);
@@ -1462,16 +1467,16 @@ implementation
                         { objectsymtable, it means it's part of self
                           if only method from which it was called is
                           not class static                          }
-                        if (srsymtable.symtabletype=ObjectSymtable) then
+                        if (srsymtable.symtabletype in [ObjectSymtable,recordsymtable]) then
                           if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
-                            p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef._class))
+                            p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef.struct))
                           else
                             p1:=load_self_node;
                         { now, if the field itself is part of an objectsymtab }
                         { (it can be even if it was found in a withsymtable,  }
                         {  e.g., "with classinstance do field := 5"), then    }
                         { let do_member_read handle it                        }
-                        if (srsym.owner.symtabletype=ObjectSymtable) then
+                        if (srsym.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
                           do_member_read(tobjectdef(hdef),getaddr,srsym,p1,again,[])
                         else
                           { otherwise it's a regular record subscript }
@@ -1502,20 +1507,20 @@ implementation
                          current_module.flags:=current_module.flags or uf_uses_variants;
                        if try_to_consume(_LKLAMMER) then
                         begin
-                          p1:=comp_expr(true);
+                          p1:=comp_expr(true,false);
                           consume(_RKLAMMER);
                           p1:=ctypeconvnode.create_explicit(p1,hdef);
                         end
                        else { not LKLAMMER }
                         if (token=_POINT) and
-                           is_object(hdef) then
+                           (is_object(hdef) or is_record(hdef)) then
                          begin
                            consume(_POINT);
                            { handles calling methods declared in parent objects
                              using "parentobject.methodname()" }
-                           if assigned(current_objectdef) and
+                           if assigned(current_structdef) and
                               not(getaddr) and
-                              current_objectdef.is_related(tobjectdef(hdef)) then
+                              current_structdef.is_related(hdef) then
                              begin
                                p1:=ctypenode.create(hdef);
                                { search also in inherited methods }
@@ -1533,18 +1538,12 @@ implementation
                               p1:=ctypenode.create(hdef);
                               { TP allows also @TMenu.Load if Load is only }
                               { defined in an anchestor class              }
-                              srsym:=search_class_member(tobjectdef(hdef),pattern);
+                              srsym:=search_struct_member(tabstractrecorddef(hdef),pattern);
                               if assigned(srsym) then
                                 begin
                                   check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
-                                  if not(getaddr) and
-                                     not((sp_static in srsym.symoptions) or (srsym.typ in [constsym,staticvarsym])) then
-                                    Message(sym_e_only_static_in_static)
-                                  else
-                                    begin
-                                      consume(_ID);
-                                      do_member_read(tobjectdef(hdef),getaddr,srsym,p1,again,[]);
-                                    end;
+                                  consume(_ID);
+                                  do_member_read(tobjectdef(hdef),getaddr,srsym,p1,again,[]);
                                 end
                               else
                                 Message1(sym_e_id_no_member,orgpattern);
@@ -1564,7 +1563,7 @@ implementation
                                 p1:=ctypenode.create(hdef);
                                 { TP allows also @TMenu.Load if Load is only }
                                 { defined in an anchestor class              }
-                                srsym:=search_class_member(tobjectdef(hdef),pattern);
+                                srsym:=search_struct_member(tobjectdef(hdef),pattern);
                                 if assigned(srsym) then
                                  begin
                                    check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
@@ -1618,7 +1617,7 @@ implementation
                       begin
                         { not srsymtable.symtabletype since that can be }
                         { withsymtable as well                          }
-                        if (srsym.owner.symtabletype=ObjectSymtable) then
+                        if (srsym.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
                           do_member_read(tobjectdef(hdef),getaddr,srsym,p1,again,[])
                         else
                           { no procsyms in records (yet) }
@@ -1643,7 +1642,7 @@ implementation
                     { property of a class/object? }
                     if is_member_read(srsym,srsymtable,p1,hdef) then
                       begin
-                        if (srsymtable.symtabletype=ObjectSymtable) then
+                        if (srsymtable.symtabletype in [ObjectSymtable,recordsymtable]) then
                            if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
                           { no self node in static class methods }
                             p1:=cloadvmtaddrnode.create(ctypenode.create(hdef))
@@ -1651,7 +1650,7 @@ implementation
                             p1:=load_self_node;
                         { not srsymtable.symtabletype since that can be }
                         { withsymtable as well                          }
-                        if (srsym.owner.symtabletype=ObjectSymtable) then
+                        if (srsym.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
                           do_member_read(tobjectdef(hdef),getaddr,srsym,p1,again,[])
                         else
                           { no propertysyms in records (yet) }
@@ -1733,10 +1732,10 @@ implementation
               { nested array constructors are not allowed, see also tests/webtbs/tw17213.pp }
               old_allow_array_constructor:=allow_array_constructor;
               allow_array_constructor:=false;
-              p1:=comp_expr(true);
+              p1:=comp_expr(true,false);
               if try_to_consume(_POINTPOINT) then
                 begin
-                  p2:=comp_expr(true);
+                  p2:=comp_expr(true,false);
                   p1:=carrayconstructorrangenode.create(p1,p2);
                 end;
                { insert at the end of the tree, to get the correct order }
@@ -1774,14 +1773,14 @@ implementation
                 else if try_to_consume(_LECKKLAMMER) then
                   begin
                     repeat
-                      comp_expr(true);
+                      comp_expr(true,false);
                     until not try_to_consume(_COMMA);
                     consume(_RECKKLAMMER);
                   end
                 else if try_to_consume(_LKLAMMER) then
                   begin
                     repeat
-                      comp_expr(true);
+                      comp_expr(true,false);
                     until not try_to_consume(_COMMA);
                     consume(_RKLAMMER);
                   end
@@ -1812,7 +1811,7 @@ implementation
 
             countindices:=0;
             repeat
-              p4:=comp_expr(true);
+              p4:=comp_expr(true,false);
 
               addstatement(newstatement,cassignmentnode.create(
                 ctemprefnode.create_offset(temp,countindices*s32inttype.size),p4));
@@ -1828,7 +1827,7 @@ implementation
             if token=_ASSIGNMENT then
               begin
                 consume(_ASSIGNMENT);
-                p4:=comp_expr(true);
+                p4:=comp_expr(true,false);
 
                 { create call to fpc_vararray_put }
                 paras:=ccallparanode.create(cordconstnode.create
@@ -1958,10 +1957,10 @@ implementation
                                  if (tpointerdef(p1.resultdef).pointeddef.typ=arraydef) and
                                     (m_autoderef in current_settings.modeswitches) then
                                    p1:=cderefnode.create(p1);
-                                 p2:=comp_expr(true);
+                                 p2:=comp_expr(true,false);
                                  { Support Pbytevar[0..9] which returns array [0..9].}
                                  if try_to_consume(_POINTPOINT) then
-                                   p2:=crangenode.create(p2,comp_expr(true));
+                                   p2:=crangenode.create(p2,comp_expr(true,false));
                                  p1:=cvecnode.create(p1,p2);
                               end;
                             variantdef:
@@ -1972,15 +1971,15 @@ implementation
                               end;
                             stringdef :
                               begin
-                                p2:=comp_expr(true);
+                                p2:=comp_expr(true,false);
                                 { Support string[0..9] which returns array [0..9] of char.}
                                 if try_to_consume(_POINTPOINT) then
-                                  p2:=crangenode.create(p2,comp_expr(true));
+                                  p2:=crangenode.create(p2,comp_expr(true,false));
                                 p1:=cvecnode.create(p1,p2);
                               end;
                             arraydef:
                               begin
-                                p2:=comp_expr(true);
+                                p2:=comp_expr(true,false);
                                 { support SEG:OFS for go32v2 Mem[] }
                                 if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
                                    (p1.nodetype=loadn) and
@@ -1994,11 +1993,11 @@ implementation
                                     if try_to_consume(_COLON) then
                                      begin
                                        p3:=caddnode.create(muln,cordconstnode.create($10,s32inttype,false),p2);
-                                       p2:=comp_expr(true);
+                                       p2:=comp_expr(true,false);
                                        p2:=caddnode.create(addn,p2,p3);
                                        if try_to_consume(_POINTPOINT) then
                                          { Support mem[$a000:$0000..$07ff] which returns array [0..$7ff] of memtype.}
-                                         p2:=crangenode.create(p2,caddnode.create(addn,comp_expr(true),p3.getcopy));
+                                         p2:=crangenode.create(p2,caddnode.create(addn,comp_expr(true,false),p3.getcopy));
                                        p1:=cvecnode.create(p1,p2);
                                        include(tvecnode(p1).flags,nf_memseg);
                                        include(tvecnode(p1).flags,nf_memindex);
@@ -2007,7 +2006,7 @@ implementation
                                      begin
                                        if try_to_consume(_POINTPOINT) then
                                          { Support mem[$80000000..$80000002] which returns array [0..2] of memtype.}
-                                         p2:=crangenode.create(p2,comp_expr(true));
+                                         p2:=crangenode.create(p2,comp_expr(true,false));
                                        p1:=cvecnode.create(p1,p2);
                                        include(tvecnode(p1).flags,nf_memindex);
                                      end;
@@ -2016,7 +2015,7 @@ implementation
                                   begin
                                     if try_to_consume(_POINTPOINT) then
                                       { Support arrayvar[0..9] which returns array [0..9] of arraytype.}
-                                      p2:=crangenode.create(p2,comp_expr(true));
+                                      p2:=crangenode.create(p2,comp_expr(true,false));
                                     p1:=cvecnode.create(p1,p2);
                                   end;
                               end;
@@ -2026,7 +2025,7 @@ implementation
                                   Message(parser_e_invalid_qualifier);
                                 p1.destroy;
                                 p1:=cerrornode.create;
-                                comp_expr(true);
+                                comp_expr(true,false);
                                 again:=false;
                               end;
                           end;
@@ -2117,7 +2116,7 @@ implementation
                                  begin
                                    consume(_ASSIGNMENT);
                                    { read the expression }
-                                   p3:=comp_expr(true);
+                                   p3:=comp_expr(true,false);
                                    { concat value parameter too }
                                    p2:=ccallparanode.create(p3,p2);
                                    { passing p3 here is only for information purposes }
@@ -2238,7 +2237,7 @@ implementation
                          begin
                            if try_to_consume(_LKLAMMER) then
                              begin
-                               p1:=comp_expr(true);
+                               p1:=comp_expr(true,false);
                                consume(_RKLAMMER);
                                p1:=ctypeconvnode.create_explicit(p1,p1.resultdef);
                              end
@@ -2313,7 +2312,7 @@ implementation
            { Handle references to self }
            if (idtoken=_SELF) and
               not(block_type in [bt_const,bt_type,bt_const_type,bt_var_type]) and
-              assigned(current_objectdef) then
+              assigned(current_structdef) then
              begin
                p1:=load_self_node;
                consume(_ID);
@@ -2341,7 +2340,7 @@ implementation
                 begin
                   consume(_RETURN);
                   if not(token in [_SEMICOLON,_ELSE,_END]) then
-                    p1 := cexitnode.create(comp_expr(true))
+                    p1 := cexitnode.create(comp_expr(true,false))
                   else
                     p1 := cexitnode.create(nil);
                 end;
@@ -2350,7 +2349,8 @@ implementation
                  again:=true;
                  consume(_INHERITED);
                  if assigned(current_procinfo) and
-                    assigned(current_objectdef) then
+                    assigned(current_structdef) and
+                    (current_structdef.typ=objectdef) then
                   begin
                     hclassdef:=current_objectdef.childof;
                     { Objective-C categories *replace* methods in the class
@@ -2527,7 +2527,7 @@ implementation
                  { STRING can be also a type cast }
                  if try_to_consume(_LKLAMMER) then
                   begin
-                    p1:=comp_expr(true);
+                    p1:=comp_expr(true,false);
                     consume(_RKLAMMER);
                     p1:=ctypeconvnode.create_explicit(p1,hdef);
                     { handle postfix operators here e.g. string(a)[10] }
@@ -2545,7 +2545,7 @@ implementation
                  { FILE can be also a type cast }
                  if try_to_consume(_LKLAMMER) then
                   begin
-                    p1:=comp_expr(true);
+                    p1:=comp_expr(true,false);
                     consume(_RKLAMMER);
                     p1:=ctypeconvnode.create_explicit(p1,hdef);
                     { handle postfix operators here e.g. string(a)[10] }
@@ -2589,7 +2589,7 @@ implementation
                  { support both @<x> and @(<x>) }
                  if try_to_consume(_LKLAMMER) then
                   begin
-                    p1:=factor(true);
+                    p1:=factor(true,false);
                     if token in [_CARET,_POINT,_LECKKLAMMER] then
                      begin
                        again:=true;
@@ -2599,7 +2599,7 @@ implementation
                     consume(_RKLAMMER);
                   end
                  else
-                  p1:=factor(true);
+                  p1:=factor(true,false);
                  if token in [_CARET,_POINT,_LECKKLAMMER] then
                   begin
                     again:=true;
@@ -2621,7 +2621,7 @@ implementation
              _LKLAMMER :
                begin
                  consume(_LKLAMMER);
-                 p1:=comp_expr(true);
+                 p1:=comp_expr(true,false);
                  consume(_RKLAMMER);
                  { it's not a good solution     }
                  { but (a+b)^ makes some problems  }
@@ -2642,7 +2642,7 @@ implementation
              _PLUS :
                begin
                  consume(_PLUS);
-                 p1:=factor(false);
+                 p1:=factor(false,false);
                  { we must generate a new node to do 0+<p1> otherwise the + will
                    not be checked }
                  p1:=caddnode.create(addn,genintconstnode(0),p1);
@@ -2656,7 +2656,7 @@ implementation
                       { ugly hack, but necessary to be able to parse }
                       { -9223372036854775808 as int64 (JM)           }
                       pattern := '-'+pattern;
-                      p1:=sub_expr(oppower,false);
+                      p1:=sub_expr(oppower,false,false);
                       {  -1 ** 4 should be - (1 ** 4) and not
                          (-1) ** 4
                          This was the reason of tw0869.pp test failure PM }
@@ -2679,7 +2679,7 @@ implementation
                     end
                  else
                    begin
-                     p1:=sub_expr(oppower,false);
+                     p1:=sub_expr(oppower,false,false);
                      p1:=cunaryminusnode.create(p1);
                    end;
                end;
@@ -2687,7 +2687,7 @@ implementation
              _OP_NOT :
                begin
                  consume(_OP_NOT);
-                 p1:=factor(false);
+                 p1:=factor(false,false);
                  p1:=cnotnode.create(p1);
                end;
 
@@ -2725,7 +2725,7 @@ implementation
                }
                consume(_OBJCPROTOCOL);
                consume(_LKLAMMER);
-               p1:=factor(false);
+               p1:=factor(false,false);
                consume(_RKLAMMER);
                p1:=cinlinenode.create(in_objc_protocol_x,false,p1);
              end;
@@ -2776,7 +2776,7 @@ implementation
            _OP_AS,_OP_IS,_OP_AND,_AMPERSAND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR],
           [_STARSTAR] );
 
-    function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):tnode;
+    function sub_expr(pred_level:Toperator_precedence;accept_equal,typeonly:boolean):tnode;
     {Reads a subexpression while the operators are of the current precedence
      level, or any higher level. Replaces the old term, simpl_expr and
      simpl2_expr.}
@@ -2786,9 +2786,9 @@ implementation
         filepos : tfileposinfo;
       begin
         if pred_level=highest_precedence then
-          p1:=factor(false)
+          p1:=factor(false,typeonly)
         else
-          p1:=sub_expr(succ(pred_level),true);
+          p1:=sub_expr(succ(pred_level),true,typeonly);
         repeat
           if (token in operator_levels[pred_level]) and
              ((token<>_EQUAL) or accept_equal) then
@@ -2797,9 +2797,9 @@ implementation
              filepos:=current_tokenpos;
              consume(token);
              if pred_level=highest_precedence then
-               p2:=factor(false)
+               p2:=factor(false,false)
              else
-               p2:=sub_expr(succ(pred_level),true);
+               p2:=sub_expr(succ(pred_level),true,typeonly);
              case oldt of
                _PLUS :
                  p1:=caddnode.create(addn,p1,p2);
@@ -2869,14 +2869,14 @@ implementation
       end;
 
 
-    function comp_expr(accept_equal : boolean):tnode;
+    function comp_expr(accept_equal,typeonly:boolean):tnode;
       var
          oldafterassignment : boolean;
          p1 : tnode;
       begin
          oldafterassignment:=afterassignment;
          afterassignment:=true;
-         p1:=sub_expr(opcompare,accept_equal);
+         p1:=sub_expr(opcompare,accept_equal,typeonly);
          { get the resultdef for this expression }
          if not assigned(p1.resultdef) then
           do_typecheckpass(p1);
@@ -2895,7 +2895,7 @@ implementation
 
       begin
          oldafterassignment:=afterassignment;
-         p1:=sub_expr(opcompare,true);
+         p1:=sub_expr(opcompare,true,false);
          { get the resultdef for this expression }
          if not assigned(p1.resultdef) and
             dotypecheck then
@@ -2908,7 +2908,7 @@ implementation
            _POINTPOINT :
              begin
                 consume(_POINTPOINT);
-                p2:=sub_expr(opcompare,true);
+                p2:=sub_expr(opcompare,true,false);
                 p1:=crangenode.create(p1,p2);
              end;
            _ASSIGNMENT :
@@ -2916,7 +2916,7 @@ implementation
                 consume(_ASSIGNMENT);
                 if (p1.resultdef.typ=procvardef) then
                   getprocvardef:=tprocvardef(p1.resultdef);
-                p2:=sub_expr(opcompare,true);
+                p2:=sub_expr(opcompare,true,false);
                 if assigned(getprocvardef) then
                   handle_procvar(getprocvardef,p2);
                 getprocvardef:=nil;
@@ -2925,25 +2925,25 @@ implementation
            _PLUSASN :
              begin
                consume(_PLUSASN);
-               p2:=sub_expr(opcompare,true);
+               p2:=sub_expr(opcompare,true,false);
                p1:=gen_c_style_operator(addn,p1,p2);
             end;
           _MINUSASN :
             begin
                consume(_MINUSASN);
-               p2:=sub_expr(opcompare,true);
+               p2:=sub_expr(opcompare,true,false);
                p1:=gen_c_style_operator(subn,p1,p2);
             end;
           _STARASN :
             begin
                consume(_STARASN  );
-               p2:=sub_expr(opcompare,true);
+               p2:=sub_expr(opcompare,true,false);
                p1:=gen_c_style_operator(muln,p1,p2);
             end;
           _SLASHASN :
             begin
                consume(_SLASHASN  );
-               p2:=sub_expr(opcompare,true);
+               p2:=sub_expr(opcompare,true,false);
                p1:=gen_c_style_operator(slashn,p1,p2);
             end;
           else
@@ -2966,7 +2966,7 @@ implementation
       p:tnode;
     begin
       result:=0;
-      p:=comp_expr(true);
+      p:=comp_expr(true,false);
       if not codegenerror then
        begin
          if (p.nodetype<>ordconstn) or
@@ -2986,7 +2986,7 @@ implementation
       p:tnode;
     begin
       get_stringconst:='';
-      p:=comp_expr(true);
+      p:=comp_expr(true,false);
       if p.nodetype<>stringconstn then
         begin
           if (p.nodetype=ordconstn) and is_char(p.resultdef) then

+ 8 - 8
compiler/pinline.pas

@@ -76,7 +76,7 @@ implementation
         storepos : tfileposinfo;
       begin
         consume(_LKLAMMER);
-        p:=comp_expr(true);
+        p:=comp_expr(true,false);
         { calc return type }
         if is_new then
           begin
@@ -98,12 +98,12 @@ implementation
               classh := classh.childof;
             if is_new then
               begin
-                sym:=search_class_member(classh,'CREATE');
+                sym:=search_struct_member(classh,'CREATE');
                 p2 := cloadvmtaddrnode.create(ctypenode.create(p.resultdef));
               end
             else
               begin
-                sym:=search_class_member(classh,'FREE');
+                sym:=search_struct_member(classh,'FREE');
                 p2 := p;
              end;
 
@@ -161,7 +161,7 @@ implementation
               begin
                  Message1(type_e_pointer_type_expected,p.resultdef.typename);
                  p.free;
-                 p:=factor(false);
+                 p:=factor(false,false);
                  p.free;
                  consume(_RKLAMMER);
                  new_dispose_statement:=cerrornode.create;
@@ -172,7 +172,7 @@ implementation
               begin
                  Message(parser_e_pointer_to_class_expected);
                  p.free;
-                 new_dispose_statement:=factor(false);
+                 new_dispose_statement:=factor(false,false);
                  consume_all_until(_RKLAMMER);
                  consume(_RKLAMMER);
                  exit;
@@ -182,7 +182,7 @@ implementation
             if is_class(classh) then
               begin
                  Message(parser_e_no_new_or_dispose_for_classes);
-                 new_dispose_statement:=factor(false);
+                 new_dispose_statement:=factor(false,false);
                  consume_all_until(_RKLAMMER);
                  consume(_RKLAMMER);
                  exit;
@@ -190,7 +190,7 @@ implementation
             { search cons-/destructor, also in parent classes }
             storepos:=current_tokenpos;
             current_tokenpos:=destructorpos;
-            sym:=search_class_member(classh,destructorname);
+            sym:=search_struct_member(classh,destructorname);
             current_tokenpos:=storepos;
 
             { the second parameter of new/dispose must be a call }
@@ -353,7 +353,7 @@ implementation
         again  : boolean; { dummy for do_proc_call }
       begin
         consume(_LKLAMMER);
-        p1:=factor(false);
+        p1:=factor(false,false);
         if p1.nodetype<>typen then
          begin
            Message(type_e_type_id_expected);

+ 14 - 15
compiler/pstatmnt.pas

@@ -71,7 +71,7 @@ implementation
          ex,if_a,else_a : tnode;
       begin
          consume(_IF);
-         ex:=comp_expr(true);
+         ex:=comp_expr(true,false);
          consume(_THEN);
          if token<>_ELSE then
            if_a:=statement
@@ -125,7 +125,7 @@ implementation
          casenode : tcasenode;
       begin
          consume(_CASE);
-         caseexpr:=comp_expr(true);
+         caseexpr:=comp_expr(true,false);
          { determines result type }
          do_typecheckpass(caseexpr);
          { variants must be accepted, but first they must be converted to integer }
@@ -300,7 +300,7 @@ implementation
          consume(_UNTIL);
 
          first:=cblocknode.create(first);
-         p_e:=comp_expr(true);
+         p_e:=comp_expr(true,false);
          result:=cwhilerepeatnode.create(p_e,first,false,true);
       end;
 
@@ -312,7 +312,7 @@ implementation
 
       begin
          consume(_WHILE);
-         p_e:=comp_expr(true);
+         p_e:=comp_expr(true,false);
          consume(_DO);
          p_a:=statement;
          result:=cwhilerepeatnode.create(p_e,p_a,true,false);
@@ -424,7 +424,7 @@ implementation
              else
                MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
 
-             hfrom:=comp_expr(true);
+             hfrom:=comp_expr(true,false);
 
              if try_to_consume(_DOWNTO) then
                backward:=true
@@ -434,7 +434,7 @@ implementation
                  backward:=false;
                end;
 
-             hto:=comp_expr(true);
+             hto:=comp_expr(true,false);
              consume(_DO);
 
              { Check if the constants fit in the range }
@@ -471,7 +471,7 @@ implementation
             var
               expr: tnode;
             begin
-              expr:=comp_expr(true);
+              expr:=comp_expr(true,false);
 
               consume(_DO);
 
@@ -490,7 +490,7 @@ implementation
          { parse loop header }
          consume(_FOR);
 
-         hloopvar:=factor(false);
+         hloopvar:=factor(false,false);
          valid_for_loopvar(hloopvar,true);
 
          if try_to_consume(_ASSIGNMENT) then
@@ -533,7 +533,7 @@ implementation
 
 
       begin
-         p:=comp_expr(true);
+         p:=comp_expr(true,false);
          do_typecheckpass(p);
 
          if (p.nodetype=vecn) and
@@ -725,12 +725,12 @@ implementation
          if not(token in endtokens) then
            begin
               { object }
-              pobj:=comp_expr(true);
+              pobj:=comp_expr(true,false);
               if try_to_consume(_AT) then
                 begin
-                   paddr:=comp_expr(true);
+                   paddr:=comp_expr(true,false);
                    if try_to_consume(_COMMA) then
-                     pframe:=comp_expr(true);
+                     pframe:=comp_expr(true,false);
                 end;
            end
          else
@@ -1204,8 +1204,7 @@ implementation
                     { can be nil in case there was an error in the expression }
                     assigned(tcallnode(p).procdefinition) and
                     not((tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
-                        assigned(tprocdef(tcallnode(p).procdefinition)._class) and
-                        is_object(tprocdef(tcallnode(p).procdefinition)._class)) then
+                        is_object(tprocdef(tcallnode(p).procdefinition).struct)) then
                    Message(parser_e_illegal_expression);
                end;
              code:=p;
@@ -1314,7 +1313,7 @@ implementation
              if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
                inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
              if (locals=0) and
-                (current_procinfo.procdef.owner.symtabletype<>ObjectSymtable) and
+                not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
                 (not assigned(current_procinfo.procdef.funcretsym) or
                  (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
                 not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then

+ 42 - 42
compiler/psub.pas

@@ -290,15 +290,15 @@ implementation
       begin
         result:=internalstatements(newstatement);
 
-        if assigned(current_objectdef) then
+        if assigned(current_structdef) then
           begin
             { a constructor needs a help procedure }
             if (current_procinfo.procdef.proctypeoption=potype_constructor) then
               begin
-                if is_class(current_objectdef) then
+                if is_class(current_structdef) then
                   begin
                     include(current_procinfo.flags,pi_needs_implicit_finally);
-                    srsym:=search_class_member(current_objectdef,'NEWINSTANCE');
+                    srsym:=search_struct_member(current_objectdef,'NEWINSTANCE');
                     if assigned(srsym) and
                        (srsym.typ=procsym) then
                       begin
@@ -320,7 +320,7 @@ implementation
                       internalerror(200305108);
                   end
                 else
-                  if is_object(current_objectdef) then
+                  if is_object(current_structdef) then
                     begin
                       { parameter 3 : vmt_offset }
                       { parameter 2 : address of pointer to vmt,
@@ -359,9 +359,9 @@ implementation
 
             { maybe call BeforeDestruction for classes }
             if (current_procinfo.procdef.proctypeoption=potype_destructor) and
-               is_class(current_objectdef) then
+               is_class(current_structdef) then
               begin
-                srsym:=search_class_member(current_objectdef,'BEFOREDESTRUCTION');
+                srsym:=search_struct_member(current_objectdef,'BEFOREDESTRUCTION');
                 if assigned(srsym) and
                    (srsym.typ=procsym) then
                   begin
@@ -393,7 +393,7 @@ implementation
       begin
         result:=internalstatements(newstatement);
 
-        if assigned(current_objectdef) then
+        if assigned(current_structdef) then
           begin
             { Don't test self and the vmt here. The reason is that  }
             { a constructor already checks whether these are valid  }
@@ -406,9 +406,9 @@ implementation
             { a destructor needs a help procedure }
             if (current_procinfo.procdef.proctypeoption=potype_destructor) then
               begin
-                if is_class(current_objectdef) then
+                if is_class(current_structdef) then
                   begin
-                    srsym:=search_class_member(current_objectdef,'FREEINSTANCE');
+                    srsym:=search_struct_member(current_objectdef,'FREEINSTANCE');
                     if assigned(srsym) and
                        (srsym.typ=procsym) then
                       begin
@@ -430,7 +430,7 @@ implementation
                       internalerror(200305108);
                   end
                 else
-                  if is_object(current_objectdef) then
+                  if is_object(current_structdef) then
                     begin
                       { finalize object data }
                       if is_managed_type(current_objectdef) then
@@ -471,7 +471,7 @@ implementation
 
         { a constructor needs call destructor (if available) when it
           is not inherited }
-        if not assigned(current_objectdef) or
+        if not assigned(current_structdef) or
            (current_procinfo.procdef.proctypeoption<>potype_constructor) then
           begin
             { no constructor }
@@ -495,7 +495,7 @@ implementation
                 { if safecall is used for a class method we need to call }
                 { SafecallException virtual method                       }
                 { In other case we return E_UNEXPECTED error value       }
-                if is_class(current_procinfo.procdef._class) then
+                if is_class(current_procinfo.procdef.struct) then
                   begin
                     { temp variable to store exception address }
                     exceptaddrnode:=ctempcreatenode.create(voidpointertype,voidpointertype.size,
@@ -513,7 +513,7 @@ implementation
                       cassignmentnode.create(
                         ctemprefnode.create(exceptobjnode),
                         ccallnode.createintern('fpc_popobjectstack', nil)));
-                    exceptsym:=search_class_member(current_procinfo.procdef._class,'SAFECALLEXCEPTION');
+                    exceptsym:=search_struct_member(tobjectdef(current_procinfo.procdef.struct),'SAFECALLEXCEPTION');
                     addstatement(newstatement,
                       cassignmentnode.create(
                         cloadnode.create(sym,sym.Owner),
@@ -595,7 +595,7 @@ implementation
         newstatement: tstatementnode;
         pd: tprocdef;
       begin
-        if assigned(current_objectdef) and
+        if assigned(current_structdef) and
            (current_procinfo.procdef.proctypeoption=potype_constructor) then
           begin
             { Don't test self and the vmt here. See generate_bodyexit_block }
@@ -604,9 +604,9 @@ implementation
             current_settings.localswitches:=oldlocalswitches-[cs_check_object,cs_check_range];
 
             { call AfterConstruction for classes }
-            if is_class(current_objectdef) then
+            if is_class(current_structdef) then
               begin
-                srsym:=search_class_member(current_objectdef,'AFTERCONSTRUCTION');
+                srsym:=search_struct_member(current_objectdef,'AFTERCONSTRUCTION');
                 if assigned(srsym) and
                    (srsym.typ=procsym) then
                   begin
@@ -806,7 +806,7 @@ implementation
         old_current_procinfo : tprocinfo;
         oldmaxfpuregisters : longint;
         oldfilepos : tfileposinfo;
-        old_current_objectdef : tobjectdef;
+        old_current_structdef : tabstractrecorddef;
         templist : TAsmList;
         headertai : tai;
         i : integer;
@@ -833,12 +833,12 @@ implementation
 
         old_current_procinfo:=current_procinfo;
         oldfilepos:=current_filepos;
-        old_current_objectdef:=current_objectdef;
+        old_current_structdef:=current_structdef;
         oldmaxfpuregisters:=current_settings.maxfpuregisters;
 
         current_procinfo:=self;
         current_filepos:=entrypos;
-        current_objectdef:=procdef._class;
+        current_structdef:=procdef.struct;
 
         templist:=TAsmList.create;
 
@@ -1265,7 +1265,7 @@ implementation
         templist.free;
         current_settings.maxfpuregisters:=oldmaxfpuregisters;
         current_filepos:=oldfilepos;
-        current_objectdef:=old_current_objectdef;
+        current_structdef:=old_current_structdef;
         current_procinfo:=old_current_procinfo;
       end;
 
@@ -1273,11 +1273,11 @@ implementation
     procedure tcgprocinfo.add_to_symtablestack;
       begin
         { insert symtables for the class, but only if it is no nested function }
-        if assigned(procdef._class) and
+        if assigned(procdef.struct) and
            not(assigned(parent) and
                assigned(parent.procdef) and
-               assigned(parent.procdef._class)) then
-          push_nested_hierarchy(procdef._class);
+               assigned(parent.procdef.struct)) then
+          push_nested_hierarchy(procdef.struct);
 
         { insert parasymtable in symtablestack when parsing
           a function }
@@ -1303,11 +1303,11 @@ implementation
           symtablestack.pop(procdef.parast);
 
         { remove symtables for the class, but only if it is no nested function }
-        if assigned(procdef._class) and
+        if assigned(procdef.struct) and
            not(assigned(parent) and
                assigned(parent.procdef) and
-               assigned(parent.procdef._class)) then
-          pop_nested_hierarchy(procdef._class);
+               assigned(parent.procdef.struct)) then
+          pop_nested_hierarchy(procdef.struct);
       end;
 
 
@@ -1379,22 +1379,22 @@ implementation
          old_current_procinfo : tprocinfo;
          old_block_type : tblock_type;
          st : TSymtable;
-         old_current_objectdef,
+         old_current_structdef: tabstractrecorddef;
          old_current_genericdef,
          old_current_specializedef : tobjectdef;
       begin
          old_current_procinfo:=current_procinfo;
          old_block_type:=block_type;
-         old_current_objectdef:=current_objectdef;
+         old_current_structdef:=current_structdef;
          old_current_genericdef:=current_genericdef;
          old_current_specializedef:=current_specializedef;
 
          current_procinfo:=self;
-         current_objectdef:=procdef._class;
-         if assigned(current_objectdef) and (df_generic in current_objectdef.defoptions) then
-           current_genericdef:=current_objectdef;
-         if assigned(current_objectdef) and (df_specialization in current_objectdef.defoptions) then
-           current_specializedef:=current_objectdef;
+         current_structdef:=procdef.struct;
+         if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
+           current_genericdef:=tobjectdef(current_structdef);
+         if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
+           current_specializedef:=tobjectdef(current_structdef);
 
          { calculate the lexical level }
          if procdef.parast.symtablelevel>maxnesting then
@@ -1500,7 +1500,7 @@ implementation
 {    aktstate.destroy;}
     {$endif state_tracking}
 
-         current_objectdef:=old_current_objectdef;
+         current_structdef:=old_current_structdef;
          current_genericdef:=old_current_genericdef;
          current_specializedef:=old_current_specializedef;
          current_procinfo:=old_current_procinfo;
@@ -1646,7 +1646,7 @@ implementation
 
       var
         old_current_procinfo : tprocinfo;
-        old_current_objectdef,
+        old_current_structdef: tabstractrecorddef;
         old_current_genericdef,
         old_current_specializedef : tobjectdef;
         pdflags    : tpdflags;
@@ -1655,19 +1655,19 @@ implementation
       begin
          { save old state }
          old_current_procinfo:=current_procinfo;
-         old_current_objectdef:=current_objectdef;
+         old_current_structdef:=current_structdef;
          old_current_genericdef:=current_genericdef;
          old_current_specializedef:=current_specializedef;
 
          { reset current_procinfo.procdef to nil to be sure that nothing is writing
            to another procdef }
          current_procinfo:=nil;
-         current_objectdef:=nil;
+         current_structdef:=nil;
          current_genericdef:=nil;
          current_specializedef:=nil;
 
          { parse procedure declaration }
-         pd:=parse_proc_dec(isclassmethod, old_current_objectdef);
+         pd:=parse_proc_dec(isclassmethod,old_current_structdef);
 
          { set the default function options }
          if parse_only then
@@ -1710,8 +1710,8 @@ implementation
          if not proc_add_definition(pd) then
            begin
              { A method must be forward defined (in the object declaration) }
-             if assigned(pd._class) and
-                (not assigned(old_current_objectdef)) then
+             if assigned(pd.struct) and
+                (not assigned(old_current_structdef)) then
               begin
                 MessagePos1(pd.fileinfo,parser_e_header_dont_match_any_member,pd.fullprocname(false));
                 tprocsym(pd.procsym).write_parameter_lists(pd);
@@ -1792,7 +1792,7 @@ implementation
                current_asmdata.DefineAsmSymbol(pd.mangledname,AB_LOCAL,AT_FUNCTION);
            end;
 
-         current_objectdef:=old_current_objectdef;
+         current_structdef:=old_current_structdef;
          current_genericdef:=old_current_genericdef;
          current_specializedef:=old_current_specializedef;
          current_procinfo:=old_current_procinfo;
@@ -1842,7 +1842,7 @@ implementation
                      if not(token in [_FUNCTION,_PROCEDURE,_PROPERTY,_VAR,_CONSTRUCTOR,_DESTRUCTOR]) then
                        Message(parser_e_procedure_or_function_expected);
 
-                     if is_interface(current_objectdef) then
+                     if is_interface(current_structdef) then
                        Message(parser_e_no_static_method_in_interfaces)
                      else
                        { class methods are also allowed for Objective-C protocols }

+ 13 - 13
compiler/ptconst.pas

@@ -191,7 +191,7 @@ implementation
           end;
 
         begin
-           n:=comp_expr(true);
+           n:=comp_expr(true,false);
            { for C-style booleans, true=-1 and false=0) }
            if is_cbool(def) then
              inserttypeconv(n,def);
@@ -291,7 +291,7 @@ implementation
           n : tnode;
           value : bestreal;
         begin
-          n:=comp_expr(true);
+          n:=comp_expr(true,false);
           if is_constrealnode(n) then
             value:=trealconstnode(n).value_real
           else if is_constintnode(n) then
@@ -332,7 +332,7 @@ implementation
         var
           n : tnode;
         begin
-          n:=comp_expr(true);
+          n:=comp_expr(true,false);
           case n.nodetype of
             loadvmtaddrn:
               begin
@@ -369,7 +369,7 @@ implementation
           ll        : tasmlabel;
           varalign  : shortint;
         begin
-          p:=comp_expr(true);
+          p:=comp_expr(true,false);
           { remove equal typecasts for pointer/nil addresses }
           if (p.nodetype=typeconvn) then
             with Ttypeconvnode(p) do
@@ -587,7 +587,7 @@ implementation
           p : tnode;
           i : longint;
         begin
-          p:=comp_expr(true);
+          p:=comp_expr(true,false);
           if p.nodetype=setconstn then
             begin
               { be sure to convert to the correct result, else
@@ -622,7 +622,7 @@ implementation
         var
           p : tnode;
         begin
-          p:=comp_expr(true);
+          p:=comp_expr(true,false);
           if p.nodetype=ordconstn then
             begin
               if equal_defs(p.resultdef,def) or
@@ -653,7 +653,7 @@ implementation
           ca        : pchar;
           winlike   : boolean;
         begin
-          n:=comp_expr(true);
+          n:=comp_expr(true,false);
           { load strval and strlength of the constant tree }
           if (n.nodetype=stringconstn) or is_wide_or_unicode_string(def) or is_constwidecharnode(n) or
             ((n.nodetype=typen) and is_interfacecorba(ttypenode(n).typedef)) then
@@ -772,7 +772,7 @@ implementation
             n : tnode;
           begin
             result:=true;
-            n:=comp_expr(true);
+            n:=comp_expr(true,false);
             if (n.nodetype <> ordconstn) or
                (not equal_defs(n.resultdef,def) and
                 not is_subequal(n.resultdef,def)) then
@@ -873,7 +873,7 @@ implementation
           else if is_anychar(def.elementdef) then
             begin
                char_size:=def.elementdef.size;
-               n:=comp_expr(true);
+               n:=comp_expr(true,false);
                if n.nodetype=stringconstn then
                  begin
                    len:=tstringconstnode(n).len;
@@ -970,7 +970,7 @@ implementation
             Message(parser_e_no_procvarobj_const);
           { parse the rest too, so we can continue with error checking }
           getprocvardef:=def;
-          n:=comp_expr(true);
+          n:=comp_expr(true,false);
           getprocvardef:=nil;
           if codegenerror then
             begin
@@ -1062,7 +1062,7 @@ implementation
           { GUID }
           if (def=rec_tguid) and (token=_ID) then
             begin
-              n:=comp_expr(true);
+              n:=comp_expr(true,false);
               if n.nodetype=stringconstn then
                 handle_stringconstn
               else
@@ -1085,7 +1085,7 @@ implementation
             end;
           if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
             begin
-              n:=comp_expr(true);
+              n:=comp_expr(true,false);
               inserttypeconv(n,cshortstringtype);
               if n.nodetype=stringconstn then
                 handle_stringconstn
@@ -1278,7 +1278,7 @@ implementation
           { only allow nil for class and interface }
           if is_class_or_interface_or_dispinterface_or_objc(def) then
             begin
-              n:=comp_expr(true);
+              n:=comp_expr(true,false);
               if n.nodetype<>niln then
                 begin
                   Message(parser_e_type_const_not_possible);

+ 31 - 53
compiler/ptype.pas

@@ -191,7 +191,7 @@ implementation
           begin
             consume(_LSHARPBRACKET);
             repeat
-              pt2:=factor(false);
+              pt2:=factor(false,true);
               pt2.free;
             until not try_to_consume(_COMMA);
             consume(_RSHARPBRACKET);
@@ -227,7 +227,7 @@ implementation
                   consume(_COMMA)
                 else
                   first:=false;
-                pt2:=factor(false);
+                pt2:=factor(false,true);
                 if pt2.nodetype=typen then
                   begin
                     if df_generic in pt2.resultdef.defoptions then
@@ -253,9 +253,9 @@ implementation
           consume(_RSHARPBRACKET);
 
         { Special case if we are referencing the current defined object }
-        if assigned(current_objectdef) and
-           (current_objectdef.objname^=uspecializename) then
-          tt:=current_objectdef;
+        if assigned(current_structdef) and
+           (current_structdef.objname^=uspecializename) then
+          tt:=current_structdef;
 
         { for units specializations can already be needed in the interface, therefor we
           will use the global symtable. Programs don't have a globalsymtable and there we
@@ -373,7 +373,7 @@ implementation
         srsymtable : TSymtable;
         s,sorg : TIDString;
         t : ttoken;
-        objdef : tobjectdef;
+        structdef : tabstractrecorddef;
       begin
          s:=pattern;
          sorg:=orgpattern;
@@ -381,20 +381,20 @@ implementation
          { use of current parsed object:
             - classes can be used also in classes
             - objects can be parameters }
-         objdef:=current_objectdef;
-         while Assigned(objdef) and (objdef.typ=objectdef) do
+         structdef:=current_structdef;
+         while Assigned(structdef) and (structdef.typ in [objectdef,recorddef]) do
            begin
-             if (tobjectdef(objdef).objname^=pattern) and
+             if (structdef.objname^=pattern) and
                 (
                   (testcurobject=2) or
-                  is_class_or_interface_or_objc(objdef)
+                  is_class_or_interface_or_objc(structdef)
                 ) then
                 begin
                   consume(_ID);
-                  def:=objdef;
+                  def:=structdef;
                   exit;
                 end;
-             objdef:=tobjectdef(tobjectdef(objdef).owner.defowner);
+             structdef:=tabstractrecorddef(structdef.owner.defowner);
            end;
          { Use the special searchsym_type that ignores records and parameters }
          searchsym_type(s,srsym,srsymtable);
@@ -505,12 +505,12 @@ implementation
                                 consume(_POINT);
                                 consume(_ID);
                              end
-                            else if is_class_or_object(def) then
+                            else if is_class_or_object(def) or is_record(def) then
                               begin
-                                symtablestack.push(tobjectdef(def).symtable);
+                                symtablestack.push(tabstractrecorddef(def).symtable);
                                 consume(_POINT);
                                 id_type(t2,isforwarddef);
-                                symtablestack.pop(tobjectdef(def).symtable);
+                                symtablestack.pop(tabstractrecorddef(def).symtable);
                                 def:=t2;
                               end
                             else
@@ -584,6 +584,7 @@ implementation
           Exit;
 
         current_structdef.symtable.currentvisibility:=vis_public;
+        testcurobject:=1;
         has_destructor:=false;
         fields_allowed:=true;
         is_classdef:=false;
@@ -716,49 +717,23 @@ implementation
                    is_classdef:=true;
                  end;
               end;
-{ todo: record methods
             _PROCEDURE,
             _FUNCTION:
               begin
                 oldparse_only:=parse_only;
                 parse_only:=true;
-                pd:=parse_proc_dec(is_classdef, recorddef);
+                pd:=parse_proc_dec(is_classdef,current_structdef);
 
                 { this is for error recovery as well as forward }
                 { interface mappings, i.e. mapping to a method  }
                 { which isn't declared yet                      }
                 if assigned(pd) then
                   begin
-                    parse_object_proc_directives(pd);
-
-                    { check if dispid is set }
-                    if is_dispinterface(pd._class) and not (po_dispid in pd.procoptions) then
-                      begin
-                        pd.dispid:=pd._class.get_next_dispid;
-                        include(pd.procoptions, po_dispid);
-                      end;
-
-                    { all Macintosh Object Pascal methods are virtual.  }
-                    { this can't be a class method, because macpas mode }
-                    { has no m_class                                    }
-                    if (m_mac in current_settings.modeswitches) then
-                      include(pd.procoptions,po_virtualmethod);
-
+                    parse_record_proc_directives(pd);
                     handle_calling_convention(pd);
 
                     { add definition to procsym }
                     proc_add_definition(pd);
-
-                    { add procdef options to objectdef options }
-                    if (po_msgint in pd.procoptions) then
-                      include(current_objectdef.objectoptions,oo_has_msgint);
-                    if (po_msgstr in pd.procoptions) then
-                      include(current_objectdef.objectoptions,oo_has_msgstr);
-                    if (po_virtualmethod in pd.procoptions) then
-                      include(current_objectdef.objectoptions,oo_has_virtual);
-
-                    chkcpp(pd);
-                    chkobjc(pd);
                   end;
 
                 maybe_parse_hint_directives(pd);
@@ -767,6 +742,7 @@ implementation
                 fields_allowed:=false;
                 is_classdef:=false;
               end;
+{ todo: constructor
             _CONSTRUCTOR :
               begin
                 if (current_objectdef.symtable.currentvisibility=vis_published) and
@@ -868,6 +844,8 @@ implementation
               consume(_ID); { Give a ident expected message, like tp7 }
           end;
         until false;
+
+        testcurobject:=0;
       end;
 
     { reads a record declaration }
@@ -913,7 +891,7 @@ implementation
            lv,hv   : TConstExprInt;
            old_block_type : tblock_type;
            dospecialize : boolean;
-           objdef: TDef;
+           structdef: TDef;
         begin
            old_block_type:=block_type;
            dospecialize:=false;
@@ -922,32 +900,32 @@ implementation
               - objects can be parameters }
            if (token=_ID) then
              begin
-               objdef:=current_objectdef;
-               while Assigned(objdef) and (objdef.typ=objectdef) do
+               structdef:=current_structdef;
+               while Assigned(structdef) and (structdef.typ in [objectdef,recorddef]) do
                  begin
-                   if (tobjectdef(objdef).objname^=pattern) and
+                   if (tabstractrecorddef(structdef).objname^=pattern) and
                       (
                         (testcurobject=2) or
-                        is_class_or_interface_or_objc(objdef)
+                        is_class_or_interface_or_objc(structdef)
                       ) then
                       begin
                         consume(_ID);
-                        def:=objdef;
+                        def:=structdef;
                         exit;
                       end;
-                   objdef:=tobjectdef(tobjectdef(objdef).owner.defowner);
+                   structdef:=tdef(tabstractrecorddef(structdef).owner.defowner);
                  end;
              end;
            { Generate a specialization? }
            if try_to_consume(_SPECIALIZE) then
              dospecialize:=true;
            { we can't accept a equal in type }
-           pt1:=comp_expr(false);
+           pt1:=comp_expr(false,true);
            if not dospecialize and
               try_to_consume(_POINTPOINT) then
              begin
                { get high value of range }
-               pt2:=comp_expr(false);
+               pt2:=comp_expr(false,false);
                { make both the same type or give an error. This is not
                  done when both are integer values, because typecasting
                  between -3200..3200 will result in a signed-unsigned
@@ -1257,7 +1235,7 @@ implementation
                     begin
                        oldlocalswitches:=current_settings.localswitches;
                        include(current_settings.localswitches,cs_allow_enum_calc);
-                       p:=comp_expr(true);
+                       p:=comp_expr(true,false);
                        current_settings.localswitches:=oldlocalswitches;
                        if (p.nodetype=ordconstn) then
                         begin

+ 2 - 5
compiler/rautils.pas

@@ -1334,10 +1334,7 @@ Begin
       i:=255;
      base:=Copy(s,1,i-1);
      delete(s,1,i);
-     if st.symtabletype=ObjectSymtable then
-       sym:=search_class_member(tobjectdef(st.defowner),base)
-     else
-       sym:=tsym(st.Find(base));
+     sym:=search_struct_member(tabstractrecorddef(st.defowner),base);
      if not assigned(sym) then
       begin
         GetRecordOffsetSize:=false;
@@ -1398,7 +1395,7 @@ Begin
                  begin
                    { size = sizeof(target_system_pointer) }
                    size:=sizeof(pint);
-                   offset:=procdef._class.vmtmethodoffset(procdef.extnumber)
+                   offset:=tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber)
                  end;
              end;
            { if something comes after the procsym, it's invalid assembler syntax }

+ 21 - 13
compiler/symdef.pas

@@ -506,8 +506,8 @@ interface
           localst : TSymtable;
           funcretsym : tsym;
           funcretsymderef : tderef;
-          _class : tobjectdef;
-          _classderef : tderef;
+          struct : tabstractrecorddef;
+          structderef : tderef;
 {$if defined(powerpc) or defined(m68k)}
           { library symbol for AmigaOS/MorphOS }
           libsym : tsym;
@@ -782,6 +782,7 @@ interface
     function is_class_or_interface_or_dispinterface(def: tdef): boolean;
     function is_class_or_interface_or_dispinterface_or_objc(def: tdef): boolean;
     function is_class_or_object(def: tdef): boolean;
+    function is_record(def: tdef): boolean;
 
     procedure loadobjctypes;
     procedure maybeloadcocoatypes;
@@ -3137,7 +3138,7 @@ implementation
          forwarddef:=true;
          interfacedef:=false;
          hasforward:=false;
-         _class := nil;
+         struct := nil;
          import_dll:=nil;
          import_name:=nil;
          import_nr:=0;
@@ -3161,7 +3162,7 @@ implementation
           _mangledname:=nil;
          extnumber:=ppufile.getword;
          level:=ppufile.getbyte;
-         ppufile.getderef(_classderef);
+         ppufile.getderef(structderef);
          ppufile.getderef(procsymderef);
          ppufile.getposinfo(fileinfo);
          visibility:=tvisibility(ppufile.getbyte);
@@ -3303,7 +3304,7 @@ implementation
 
          ppufile.putword(extnumber);
          ppufile.putbyte(parast.symtablelevel);
-         ppufile.putderef(_classderef);
+         ppufile.putderef(structderef);
          ppufile.putderef(procsymderef);
          ppufile.putposinfo(fileinfo);
          ppufile.putbyte(byte(visibility));
@@ -3389,9 +3390,9 @@ implementation
         showhidden:=true;
 {$endif EXTDEBUG}
         s:='';
-        if assigned(_class) then
+        if assigned(struct) then
          begin
-           s:=_class.RttiName+'.';
+           s:=struct.RttiName+'.';
            if (po_classmethod in procoptions) and
               not (proctypeoption in [potype_class_constructor,potype_class_destructor]) then
              s:='class ' + s;
@@ -3466,7 +3467,7 @@ implementation
     procedure tprocdef.buildderef;
       begin
          inherited buildderef;
-         _classderef.build(_class);
+         structderef.build(struct);
          { procsym that originaly defined this definition, should be in the
            same symtable }
          procsymderef.build(procsym);
@@ -3500,7 +3501,7 @@ implementation
     procedure tprocdef.deref;
       begin
          inherited deref;
-         _class:=tobjectdef(_classderef.resolve);
+         struct:=tabstractrecorddef(structderef.resolve);
          { procsym that originaly defined this definition, should be in the
            same symtable }
          procsym:=tprocsym(procsymderef.resolve);
@@ -4978,7 +4979,7 @@ implementation
             else
               { all checks already done }
               exit;
-            if not(oo_is_external in pd._class.objectoptions) then
+            if not((pd.struct.typ=objectdef)and(oo_is_external in tobjectdef(pd.struct).objectoptions)) then
               begin
                 if (po_varargs in pd.procoptions) then
                   MessagePos(pd.fileinfo,parser_e_varargs_need_cdecl_and_external)
@@ -5073,11 +5074,11 @@ implementation
         if (def.typ=procdef) then
           begin
             pd.setmangledname(target_info.Cprefix+pd.cplusplusmangledname);
-            if (oo_is_external in pd._class.objectoptions) then
+            if (pd.struct.typ=objectdef) and (oo_is_external in tobjectdef(pd.struct).objectoptions) then
               begin
                 { copied from psub.read_proc }
-                if assigned(pd._class.import_lib) then
-                   current_module.AddExternalImport(pd._class.import_lib^,pd.mangledname,0,false,false)
+                if assigned(tobjectdef(pd.struct).import_lib) then
+                   current_module.AddExternalImport(tobjectdef(pd.struct).import_lib^,pd.mangledname,0,false,false)
                  else
                    begin
                      { add import name to external list for DLL scanning }
@@ -5491,6 +5492,13 @@ implementation
           (tobjectdef(def).objecttype in [odt_class,odt_object]);
       end;
 
+    function is_record(def: tdef): boolean;
+      begin
+        result:=
+          assigned(def) and
+          (def.typ=recorddef);
+      end;
+
     procedure loadobjctypes;
       begin
         objc_metaclasstype:=tpointerdef(search_named_unit_globaltype('OBJC','POBJC_CLASS',true).typedef);

+ 46 - 23
compiler/symtable.pas

@@ -213,7 +213,7 @@ interface
     function  searchsym_in_class_by_msgstr(classh:tobjectdef;const s:string;out srsym:tsym;out srsymtable:TSymtable):boolean;
     function  search_system_type(const s: TIDString): ttypesym;
     function  search_named_unit_globaltype(const unitname, typename: TIDString; throwerror: boolean): ttypesym;
-    function  search_class_member(pd : tobjectdef;const s : string):tsym;
+    function  search_struct_member(pd : tabstractrecorddef;const s : string):tsym;
     function  search_assignment_operator(from_def,to_def:Tdef):Tprocdef;
     function  search_enumerator_operator(from_def,to_def:Tdef):Tprocdef;
     function  search_class_helper(pd : tobjectdef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
@@ -1188,7 +1188,7 @@ implementation
          if not(sym.typ in [procsym,propertysym]) then
            begin
               { but private ids can be reused }
-              hsym:=search_class_member(tobjectdef(defowner),hashedid.id);
+              hsym:=search_struct_member(tobjectdef(defowner),hashedid.id);
               if assigned(hsym) and
                  (
                   (
@@ -1322,13 +1322,13 @@ implementation
           as the procsym }
         if not is_funcret_sym(sym) and
            (defowner.typ=procdef) and
-           assigned(tprocdef(defowner)._class) and
-           (tprocdef(defowner).owner.defowner=tprocdef(defowner)._class) and
+           assigned(tprocdef(defowner).struct) and
+           (tprocdef(defowner).owner.defowner=tprocdef(defowner).struct) and
            (
             not(m_delphi in current_settings.modeswitches) or
-            is_object(tprocdef(defowner)._class)
+            is_object(tprocdef(defowner).struct)
            ) then
-          result:=tprocdef(defowner)._class.symtable.checkduplicate(hashedid,sym);
+          result:=tprocdef(defowner).struct.symtable.checkduplicate(hashedid,sym);
       end;
 
 
@@ -1352,13 +1352,13 @@ implementation
           exit;
         if not(m_duplicate_names in current_settings.modeswitches) and
            (defowner.typ=procdef) and
-           assigned(tprocdef(defowner)._class) and
-           (tprocdef(defowner).owner.defowner=tprocdef(defowner)._class) and
+           assigned(tprocdef(defowner).struct) and
+           (tprocdef(defowner).owner.defowner=tprocdef(defowner).struct) and
            (
             not(m_delphi in current_settings.modeswitches) or
-            is_object(tprocdef(defowner)._class)
+            is_object(tprocdef(defowner).struct)
            ) then
-          result:=tprocdef(defowner)._class.symtable.checkduplicate(hashedid,sym);
+          result:=tprocdef(defowner).struct.symtable.checkduplicate(hashedid,sym);
       end;
 
 
@@ -1878,6 +1878,7 @@ implementation
       var
         hashedid  : THashedIDString;
         stackitem : psymtablestackitem;
+        classh : tobjectdef;
       begin
         result:=false;
         hashedid.id:=s;
@@ -1886,27 +1887,46 @@ implementation
           begin
             {
               It is not possible to have type symbols in:
-                records
                 parameters
-              Exception are classes, objects, generic definitions and specializations
+              Exception are classes, objects, records, generic definitions and specializations
               that have the parameterized types inserted in the symtable.
             }
             srsymtable:=stackitem^.symtable;
+            if (srsymtable.symtabletype=ObjectSymtable) then
+              begin
+                classh:=tobjectdef(srsymtable.defowner);
+                while assigned(classh) do
+                  begin
+                    srsymtable:=classh.symtable;
+                    srsym:=tsym(srsymtable.FindWithHash(hashedid));
+                    if assigned(srsym) and
+                       (srsym.typ=typesym) and
+                       is_visible_for_object(srsym,current_structdef) then
+                      begin
+                        addsymref(srsym);
+                        result:=true;
+                        exit;
+                      end;
+                    classh:=classh.childof;
+                  end;
+              end
+            else
             if not(srsymtable.symtabletype in [recordsymtable,ObjectSymtable,parasymtable]) or
                (assigned(srsymtable.defowner) and
                 (
                  (df_generic in tdef(srsymtable.defowner).defoptions) or
                  (df_specialization in tdef(srsymtable.defowner).defoptions) or
-                 is_class_or_object(tdef(srsymtable.defowner)))
-                ) then
+                 is_class_or_object(tdef(srsymtable.defowner)) or
+                 is_record(tdef(srsymtable.defowner))
+                )
+               ) then
               begin
                 srsym:=tsym(srsymtable.FindWithHash(hashedid));
                 if assigned(srsym) and
                    not(srsym.typ in [fieldvarsym,paravarsym]) and
                    (
                     not (srsym.owner.symtabletype in [objectsymtable,recordsymtable]) or
-                    (is_visible_for_object(srsym,current_structdef) and
-                     (srsym.typ=typesym))
+                    ((srsym.typ=typesym)and is_visible_for_object(srsym,current_structdef))
                    ) then
                   begin
                     { we need to know if a procedure references symbols
@@ -2428,17 +2448,17 @@ implementation
       end;
 
 
-    function search_class_member(pd : tobjectdef;const s : string):tsym;
+    function search_struct_member(pd : tabstractrecorddef;const s : string):tsym;
     { searches n in symtable of pd and all anchestors }
       var
         hashedid   : THashedIDString;
         srsym      : tsym;
-        orgpd      : tobjectdef;
+        orgpd      : tabstractrecorddef;
         srsymtable : tsymtable;
       begin
         { in case this is a formal objcclass, first find the real definition }
-        if (oo_is_formal in pd.objectoptions) then
-          pd:=find_real_objcclass_definition(pd,true);
+        if (pd.typ=objectdef) and (oo_is_formal in tobjectdef(pd).objectoptions) then
+          pd:=find_real_objcclass_definition(tobjectdef(pd),true);
         hashedid.id:=s;
         orgpd:=pd;
         while assigned(pd) do
@@ -2446,15 +2466,18 @@ implementation
            srsym:=tsym(pd.symtable.FindWithHash(hashedid));
            if assigned(srsym) then
             begin
-              search_class_member:=srsym;
+              search_struct_member:=srsym;
               exit;
             end;
-           pd:=pd.childof;
+           if pd.typ=objectdef then
+             pd:=tobjectdef(pd).childof
+           else
+             pd:=nil;
          end;
 
         { not found, now look for class helpers }
         if is_objcclass(pd) then
-          search_class_helper(orgpd,s,result,srsymtable)
+          search_class_helper(tobjectdef(orgpd),s,result,srsymtable)
         else
           result:=nil;
       end;

+ 4 - 0
tests/test/terecs3.pp

@@ -17,5 +17,9 @@ begin
     halt(2);
   if F.C <> 1 then
     halt(3);
+  if F.Test(3) <> 4 then
+    halt(4);
+  if F.Test1(4) <> 5 then
+    halt(5);
   WriteLn('ok');
 end.

+ 18 - 2
tests/test/terecs_u1.pp

@@ -6,19 +6,35 @@ unit terecs_u1;
 interface
 
 type
+  HWND = integer;
   TFoo = record
+    hWnd : HWND;
   private
     F1: Integer;
     F2: Byte;
   public
+    type
+      TBar = Integer;
     const
-      C = 1;
+      C: TBar = 1;
     var
-      F3: Integer;
+      F3: TBar;
       F4: Byte;
+    function Test(n: TBar): TBar;
+    class function Test1(n: TBar): TBar;
   end;
 
 implementation
 
+function TFoo.Test(n: TBar): TBar;
+begin
+  Result := F3 + F4 + n;
+end;
+
+class function TFoo.Test1(n: TBar): TBar;
+begin
+  Result := C + n;
+end;
+
 end.