* instead of declaring another type with a 'attribute' suffix, *search* for another type with a 'ATTRIBUTE' suffix (Delphi allows declaring both a TFoo and TFooAttribute in the same unit)

+ added test

git-svn-id: trunk@42362 -
This commit is contained in:
svenbarth 2019-07-12 22:05:18 +00:00
parent 869664c6da
commit 24c4b90343
6 changed files with 116 additions and 58 deletions

1
.gitattributes vendored
View File

@ -13207,6 +13207,7 @@ tests/test/tcstring1.pp svneol=native#text/pascal
tests/test/tcstring2.pp svneol=native#text/pascal tests/test/tcstring2.pp svneol=native#text/pascal
tests/test/tcustomattr1.pp svneol=native#text/pascal tests/test/tcustomattr1.pp svneol=native#text/pascal
tests/test/tcustomattr10.pp svneol=native#text/pascal tests/test/tcustomattr10.pp svneol=native#text/pascal
tests/test/tcustomattr11.pp svneol=native#text/pascal
tests/test/tcustomattr2.pp svneol=native#text/pascal tests/test/tcustomattr2.pp svneol=native#text/pascal
tests/test/tcustomattr3.pp svneol=native#text/pascal tests/test/tcustomattr3.pp svneol=native#text/pascal
tests/test/tcustomattr4.pp svneol=native#text/pascal tests/test/tcustomattr4.pp svneol=native#text/pascal

View File

@ -399,6 +399,8 @@ interface
defaultmainaliasname = 'main'; defaultmainaliasname = 'main';
mainaliasname : string = defaultmainaliasname; mainaliasname : string = defaultmainaliasname;
custom_attribute_suffix = 'ATTRIBUTE';
LTOExt: TCmdStr = ''; LTOExt: TCmdStr = '';
const const

View File

@ -92,7 +92,8 @@ interface
type type
tconsume_unitsym_flag = ( tconsume_unitsym_flag = (
cuf_consume_id, cuf_consume_id,
cuf_allow_specialize cuf_allow_specialize,
cuf_check_attr_suffix
); );
tconsume_unitsym_flags = set of tconsume_unitsym_flag; tconsume_unitsym_flags = set of tconsume_unitsym_flag;
@ -361,26 +362,38 @@ implementation
end; end;
case token of case token of
_ID: _ID:
{ system.char? (char=widechar comes from the implicit begin
uuchar unit -> override) } if cuf_check_attr_suffix in flags then
if (pattern='CHAR') and
(tmodule(tunitsym(srsym).module).globalsymtable=systemunit) then
begin
if m_default_unicodestring in current_settings.modeswitches then
searchsym_in_module(tunitsym(srsym).module,'WIDECHAR',srsym,srsymtable)
else
searchsym_in_module(tunitsym(srsym).module,'ANSICHAR',srsym,srsymtable)
end
else
if (cuf_allow_specialize in flags) and (idtoken=_SPECIALIZE) then
begin begin
consume(_ID); if searchsym_in_module(tunitsym(srsym).module,pattern+custom_attribute_suffix,srsym,srsymtable) then
is_specialize:=true; exit(true);
if token=_ID then end;
searchsym_in_module(tunitsym(srsym).module,pattern,srsym,srsymtable); { system.char? (char=widechar comes from the implicit
uuchar unit -> override) }
if (pattern='CHAR') and
(tmodule(tunitsym(srsym).module).globalsymtable=systemunit) then
begin
if m_default_unicodestring in current_settings.modeswitches then
searchsym_in_module(tunitsym(srsym).module,'WIDECHAR',srsym,srsymtable)
else
searchsym_in_module(tunitsym(srsym).module,'ANSICHAR',srsym,srsymtable)
end end
else else
searchsym_in_module(tunitsym(srsym).module,pattern,srsym,srsymtable); if (cuf_allow_specialize in flags) and (idtoken=_SPECIALIZE) then
begin
consume(_ID);
is_specialize:=true;
if token=_ID then
begin
if (cuf_check_attr_suffix in flags) and
searchsym_in_module(tunitsym(srsym).module,pattern+custom_attribute_suffix,srsym,srsymtable) then
exit(true);
searchsym_in_module(tunitsym(srsym).module,pattern,srsym,srsymtable);
end;
end
else
searchsym_in_module(tunitsym(srsym).module,pattern,srsym,srsymtable);
end;
_STRING: _STRING:
begin begin
{ system.string? } { system.string? }

View File

@ -82,30 +82,6 @@ implementation
Result := def_is_related(def, system_custom_attribute_def); Result := def_is_related(def, system_custom_attribute_def);
end; end;
procedure create_renamed_attr_type_if_needed(hdef: tobjectdef);
const
attrconst = 'attribute';
var
newname : TIDString;
newtypeattr : ttypesym;
i: integer;
begin
if not is_system_custom_attribute_descendant(hdef) then
Exit;
{ Check if the name ends with 'attribute'. }
i := Pos(attrconst, lower(hdef.typename), max(0, length(hdef.typename) - length(attrconst)));
newname:=Copy(hdef.typename, 0, i-1);
if (i > 0) and (length(newname) > 0) then
begin
{ Create a new typesym with 'attribute' removed. }
newtypeattr:=ctypesym.create(newname,hdef,true);
newtypeattr.visibility:=symtablestack.top.currentvisibility;
include(newtypeattr.symoptions,sp_implicitrename);
symtablestack.top.insert(newtypeattr);
end;
end;
function readconstant(const orgname:string;const filepos:tfileposinfo; out nodetype: tnodetype):tconstsym; function readconstant(const orgname:string;const filepos:tfileposinfo; out nodetype: tnodetype):tconstsym;
var var
hp : tconstsym; hp : tconstsym;
@ -448,7 +424,7 @@ implementation
consume(_LECKKLAMMER); consume(_LECKKLAMMER);
{ Parse attribute type } { Parse attribute type }
p := factor(false,[ef_type_only]); p := factor(false,[ef_type_only,ef_check_attr_suffix]);
if p.nodetype<> errorn then if p.nodetype<> errorn then
begin begin
typeSym := ttypesym(ttypenode(p).typesym); typeSym := ttypesym(ttypenode(p).typesym);
@ -1046,9 +1022,6 @@ implementation
if is_cppclass(hdef) then if is_cppclass(hdef) then
tobjectdef(hdef).finish_cpp_data; tobjectdef(hdef).finish_cpp_data;
if (m_prefixed_attributes in current_settings.modeswitches) then
create_renamed_attr_type_if_needed(tobjectdef(hdef));
end; end;
recorddef : recorddef :
begin begin

View File

@ -35,7 +35,8 @@ interface
texprflag = ( texprflag = (
ef_accept_equal, ef_accept_equal,
ef_type_only, ef_type_only,
ef_had_specialize ef_had_specialize,
ef_check_attr_suffix
); );
texprflags = set of texprflag; texprflags = set of texprflag;
@ -2826,6 +2827,7 @@ implementation
storedpattern: string; storedpattern: string;
callflags: tcallnodeflags; callflags: tcallnodeflags;
t : ttoken; t : ttoken;
consumeid,
wasgenericdummy, wasgenericdummy,
allowspecialize, allowspecialize,
isspecialize, isspecialize,
@ -2867,28 +2869,55 @@ implementation
end end
else else
begin begin
if ef_type_only in flags then storedpattern:=pattern;
searchsym_type(pattern,srsym,srsymtable) orgstoredpattern:=orgpattern;
else { store the position of the token before consuming it }
searchsym(pattern,srsym,srsymtable); tokenpos:=current_filepos;
consumeid:=true;
srsym:=nil;
if ef_check_attr_suffix in flags then
begin
if not (ef_type_only in flags) then
internalerror(2019063001);
consume(_ID);
consumeid:=false;
if token<>_POINT then
searchsym_type(storedpattern+custom_attribute_suffix,srsym,srsymtable);
end;
if not assigned(srsym) then
begin
if ef_type_only in flags then
searchsym_type(storedpattern,srsym,srsymtable)
else
searchsym(storedpattern,srsym,srsymtable);
end;
{ handle unit specification like System.Writeln } { handle unit specification like System.Writeln }
if not isspecialize then if not isspecialize then
begin begin
cufflags:=[cuf_consume_id]; cufflags:=[];
if consumeid then
include(cufflags,cuf_consume_id);
if allowspecialize then if allowspecialize then
include(cufflags,cuf_allow_specialize); include(cufflags,cuf_allow_specialize);
unit_found:=try_consume_unitsym(srsym,srsymtable,t,cufflags,isspecialize,pattern) if ef_check_attr_suffix in flags then
include(cufflags,cuf_check_attr_suffix);
unit_found:=try_consume_unitsym(srsym,srsymtable,t,cufflags,isspecialize,pattern);
if unit_found then
consumeid:=true;
end end
else else
begin begin
unit_found:=false; unit_found:=false;
t:=_ID; t:=_ID;
end; end;
storedpattern:=pattern; if consumeid then
orgstoredpattern:=orgpattern; begin
{ store the position of the token before consuming it } storedpattern:=pattern;
tokenpos:=current_filepos; orgstoredpattern:=orgpattern;
consume(t); { store the position of the token before consuming it }
tokenpos:=current_filepos;
consume(t);
end;
{ named parameter support } { named parameter support }
found_arg_name:=false; found_arg_name:=false;

View File

@ -0,0 +1,40 @@
program tcustomattr11;
{$mode objfpc}
{$modeswitch prefixedattributes}
uses
TypInfo;
type
TTest = class(TCustomAttribute)
end;
TTestAttribute = class(TCustomAttribute)
end;
{ the attribute with the Attribute suffix is preferred }
[TTest]
TTestObj = class
end;
var
ad: PAttributeData;
attr: TCustomAttribute;
begin
ad := GetAttributeData(TypeInfo(TTestObj));
if not Assigned(ad) then
Halt(1);
if ad^.AttributeCount <> 1 then
Halt(2);
attr := GetAttribute(ad, 0);
if not Assigned(attr) then
Halt(3);
if not (attr is TTestAttribute) then
Halt(4);
Writeln('ok');
end.