* Attributes must be assigned only to elements before the first colon

This commit is contained in:
Michaël Van Canneyt 2024-02-29 10:22:19 +01:00
parent 11f076f0e7
commit 2c9870f85a
3 changed files with 44 additions and 10 deletions

View File

@ -1084,7 +1084,7 @@ implementation
vdoptions: tvar_dec_options;
fieldlist: tfpobjectlist;
rtti_attrs_def: trtti_attribute_list;
fldCount : Integer;
attr_element_count,fldCount : Integer;
procedure parse_const;
begin
@ -1367,15 +1367,28 @@ implementation
include(vdoptions,vd_threadvar);
// Record count
fldCount:=FieldList.Count;
read_record_fields(vdoptions,fieldlist,nil,hadgeneric);
read_record_fields(vdoptions,fieldlist,nil,hadgeneric,attr_element_count);
{
attr_element_count returns the number of fields to which the attribute must be applied.
For
[someattr]
a : integer;
b : integer;
attr_element_count returns 1. For
[someattr]
a, b : integer;
it returns 2.
Basically the number of variables before the first colon.
}
if assigned(rtti_attrs_def) then
begin
{ read_record_fields can read a list of fields with the same type.
for the first fields, we simply copy. for the last one we bind.}
While (fldCount+1<FieldList.Count) do
While (attr_element_count>1) do
begin
trtti_attribute_list.copyandbind(rtti_attrs_def,tfieldvarsym(fieldlist[FldCount]).rtti_attribute_list);
inc(fldcount);
dec(attr_element_count);
end;
if fldCount<FieldList.Count then
trtti_attribute_list.bind(rtti_attrs_def,tfieldvarsym(fieldlist[FldCount]).rtti_attribute_list)

View File

@ -38,7 +38,7 @@ interface
procedure read_var_decls(options:Tvar_dec_options;out had_generic:boolean);
procedure read_record_fields(options:Tvar_dec_options; reorderlist: TFPObjectList; variantdesc: ppvariantrecdesc;out had_generic:boolean);
procedure read_record_fields(options:Tvar_dec_options; reorderlist: TFPObjectList; variantdesc: ppvariantrecdesc;out had_generic:boolean; out attr_element_count : integer);
procedure read_public_and_external(vs: tabstractvarsym);
@ -1679,7 +1679,7 @@ implementation
end;
procedure read_record_fields(options:Tvar_dec_options; reorderlist: TFPObjectList; variantdesc : ppvariantrecdesc;out had_generic:boolean);
procedure read_record_fields(options:Tvar_dec_options; reorderlist: TFPObjectList; variantdesc : ppvariantrecdesc;out had_generic:boolean; out attr_element_count : integer);
var
sc : TFPObjectList;
i : longint;
@ -1707,6 +1707,7 @@ implementation
hadgendummy,
semicoloneaten,
removeclassoption: boolean;
dummyattrelementcount : integer;
{$if defined(powerpc) or defined(powerpc64)}
tempdef: tdef;
is_first_type: boolean;
@ -1727,6 +1728,7 @@ implementation
sc:=TFPObjectList.create(false);
removeclassoption:=false;
had_generic:=false;
attr_element_count:=0;
while (token=_ID) and
not(((vd_object in options) or
((vd_record in options) and (m_advanced_records in current_settings.modeswitches))) and
@ -1775,6 +1777,9 @@ implementation
if had_generic and (sc.count=0) then
break;
consume(_COLON);
if attr_element_count=0 then
attr_element_count:=sc.Count;
typepos:=current_filepos;
read_anon_type(hdef,false);
@ -2056,7 +2061,7 @@ implementation
consume(_LKLAMMER);
inc(variantrecordlevel);
if token<>_RKLAMMER then
read_record_fields([vd_record],nil,@variantdesc^^.branches[high(variantdesc^^.branches)].nestedvariant,hadgendummy);
read_record_fields([vd_record],nil,@variantdesc^^.branches[high(variantdesc^^.branches)].nestedvariant,hadgendummy,dummyattrelementcount);
dec(variantrecordlevel);
consume(_RKLAMMER);

View File

@ -698,6 +698,7 @@ implementation
vdoptions: tvar_dec_options;
rtti_attrs_def: trtti_attribute_list;
fldCount : Integer;
attr_element_count : Integer;
procedure check_unbound_attributes;
begin
@ -894,15 +895,29 @@ implementation
if threadvarfields then
include(vdoptions,vd_threadvar);
fldCount:=current_structdef.symtable.SymList.Count;
read_record_fields(vdoptions,nil,nil,hadgeneric);
read_record_fields(vdoptions,nil,nil,hadgeneric,attr_element_count);
{
attr_element_count returns the number of fields to which the attribute must be applied.
For
[someattr]
a : integer;
b : integer;
attr_element_count returns 1. For
[someattr]
a, b : integer;
it returns 2.
Basically the number of variables before the first colon.
}
if assigned(rtti_attrs_def) then
begin
While (fldCount+1<current_structdef.symtable.SymList.Count) do
While (attr_element_count>1) do
begin
trtti_attribute_list.copyandbind(rtti_attrs_def,(current_structdef.symtable.SymList[fldCount] as tfieldvarsym).rtti_attribute_list);
inc(fldcount);
dec(attr_element_count);
end;
trtti_attribute_list.bind(rtti_attrs_def,(current_structdef.symtable.SymList[fldCount] as tfieldvarsym).rtti_attribute_list);
if fldCount<current_structdef.symtable.SymList.Count then
trtti_attribute_list.bind(rtti_attrs_def,(current_structdef.symtable.SymList[fldCount] as tfieldvarsym).rtti_attribute_list);
end;
end;
end
@ -1036,6 +1051,7 @@ implementation
recst: trecordsymtable;
hadgendummy : boolean;
alignment: Integer;
dummyattrelcount : Integer;
begin
old_current_structdef:=current_structdef;
old_current_genericdef:=current_genericdef;
@ -1100,7 +1116,7 @@ implementation
end
else
begin
read_record_fields([vd_record],nil,nil,hadgendummy);
read_record_fields([vd_record],nil,nil,hadgendummy,dummyattrelcount);
{$ifdef jvm}
{ we need a constructor to create temps, a deep copy helper, ... }
add_java_default_record_methods_intf(trecorddef(current_structdef));