mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-03 01:09:40 +01:00
compiler: types in classes:
- fix type visibility (was always public) - fix parsing of class sections after the type declaration - allow nested classes declarations + tests git-svn-id: trunk@14607 -
This commit is contained in:
parent
8de3b267a9
commit
91ed1c6e6f
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -8890,6 +8890,8 @@ tests/test/tcg1.pp svneol=native#text/plain
|
||||
tests/test/tcint64.pp svneol=native#text/plain
|
||||
tests/test/tclass1.pp svneol=native#text/plain
|
||||
tests/test/tclass10.pp svneol=native#text/pascal
|
||||
tests/test/tclass11a.pp svneol=native#text/pascal
|
||||
tests/test/tclass11b.pp svneol=native#text/pascal
|
||||
tests/test/tclass2.pp svneol=native#text/plain
|
||||
tests/test/tclass3.pp svneol=native#text/plain
|
||||
tests/test/tclass4.pp svneol=native#text/plain
|
||||
|
||||
@ -38,7 +38,7 @@ interface
|
||||
procedure const_dec;
|
||||
procedure label_dec;
|
||||
procedure type_dec;
|
||||
procedure types_dec;
|
||||
procedure types_dec(in_class: boolean);
|
||||
procedure var_dec;
|
||||
procedure threadvar_dec;
|
||||
procedure property_dec(is_classpropery: boolean);
|
||||
@ -282,7 +282,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure types_dec;
|
||||
procedure types_dec(in_class: boolean);
|
||||
|
||||
procedure get_cpp_class_external_status(od: tobjectdef);
|
||||
var
|
||||
@ -483,6 +483,7 @@ implementation
|
||||
hdef:=generrordef;
|
||||
storetokenpos:=current_tokenpos;
|
||||
newtype:=ttypesym.create(orgtypename,hdef);
|
||||
newtype.visibility:=symtablestack.top.currentvisibility;
|
||||
symtablestack.top.insert(newtype);
|
||||
current_tokenpos:=defpos;
|
||||
current_tokenpos:=storetokenpos;
|
||||
@ -619,7 +620,7 @@ implementation
|
||||
end;
|
||||
if assigned(generictypelist) then
|
||||
generictypelist.free;
|
||||
until token<>_ID;
|
||||
until (token<>_ID)or(in_class and (idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]));
|
||||
resolve_forward_types;
|
||||
block_type:=old_block_type;
|
||||
end;
|
||||
@ -629,7 +630,7 @@ implementation
|
||||
procedure type_dec;
|
||||
begin
|
||||
consume(_TYPE);
|
||||
types_dec;
|
||||
types_dec(false);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
@ -671,7 +671,7 @@ implementation
|
||||
read_record_fields([vd_object])
|
||||
end
|
||||
else
|
||||
types_dec;
|
||||
types_dec(true);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -843,7 +843,7 @@ implementation
|
||||
current_objectdef:=nil;
|
||||
|
||||
{ objects and class types can't be declared local }
|
||||
if not(symtablestack.top.symtabletype in [globalsymtable,staticsymtable]) and
|
||||
if not(symtablestack.top.symtabletype in [globalsymtable,staticsymtable,objectsymtable]) and
|
||||
not assigned(genericlist) then
|
||||
Message(parser_e_no_local_objects);
|
||||
|
||||
|
||||
@ -764,52 +764,65 @@ implementation
|
||||
(symtablestack.top.symtablelevel=main_program_level) and
|
||||
try_to_consume(_POINT) then
|
||||
begin
|
||||
{ search for object name }
|
||||
storepos:=current_tokenpos;
|
||||
current_tokenpos:=procstartfilepos;
|
||||
searchsym(sp,srsym,srsymtable);
|
||||
if not assigned(srsym) then
|
||||
begin
|
||||
identifier_not_found(orgsp);
|
||||
srsym:=generrorsym;
|
||||
end;
|
||||
current_tokenpos:=storepos;
|
||||
{ consume proc name }
|
||||
sp:=pattern;
|
||||
orgsp:=orgpattern;
|
||||
procstartfilepos:=current_tokenpos;
|
||||
consume(_ID);
|
||||
{ qualifier is class name ? }
|
||||
if (srsym.typ=typesym) and
|
||||
(ttypesym(srsym).typedef.typ=objectdef) then
|
||||
begin
|
||||
aclass:=tobjectdef(ttypesym(srsym).typedef);
|
||||
srsym:=tsym(aclass.symtable.Find(sp));
|
||||
if assigned(srsym) then
|
||||
repeat
|
||||
searchagain:=false;
|
||||
if not assigned(aclass) then
|
||||
begin
|
||||
if srsym.typ=procsym then
|
||||
aprocsym:=tprocsym(srsym)
|
||||
else
|
||||
begin
|
||||
{ we use a different error message for tp7 so it looks more compatible }
|
||||
if (m_fpc in current_settings.modeswitches) then
|
||||
Message1(parser_e_overloaded_no_procedure,srsym.realname)
|
||||
else
|
||||
Message(parser_e_methode_id_expected);
|
||||
{ rename the name to an unique name to avoid an
|
||||
error when inserting the symbol in the symtable }
|
||||
orgsp:=orgsp+'$'+tostr(current_filepos.line);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Message(parser_e_methode_id_expected);
|
||||
{ recover by making it a normal procedure instead of method }
|
||||
aclass:=nil;
|
||||
{ search for object name }
|
||||
storepos:=current_tokenpos;
|
||||
current_tokenpos:=procstartfilepos;
|
||||
searchsym(sp,srsym,srsymtable);
|
||||
if not assigned(srsym) then
|
||||
begin
|
||||
identifier_not_found(orgsp);
|
||||
srsym:=generrorsym;
|
||||
end;
|
||||
current_tokenpos:=storepos;
|
||||
end;
|
||||
end
|
||||
else
|
||||
Message(parser_e_class_id_expected);
|
||||
{ consume proc name }
|
||||
sp:=pattern;
|
||||
orgsp:=orgpattern;
|
||||
procstartfilepos:=current_tokenpos;
|
||||
consume(_ID);
|
||||
{ qualifier is class name ? }
|
||||
if (srsym.typ=typesym) and
|
||||
(ttypesym(srsym).typedef.typ=objectdef) then
|
||||
begin
|
||||
aclass:=tobjectdef(ttypesym(srsym).typedef);
|
||||
srsym:=tsym(aclass.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
|
||||
begin
|
||||
searchagain:=true;
|
||||
consume(_POINT);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ we use a different error message for tp7 so it looks more compatible }
|
||||
if (m_fpc in current_settings.modeswitches) then
|
||||
Message1(parser_e_overloaded_no_procedure,srsym.realname)
|
||||
else
|
||||
Message(parser_e_methode_id_expected);
|
||||
{ rename the name to an unique name to avoid an
|
||||
error when inserting the symbol in the symtable }
|
||||
orgsp:=orgsp+'$'+tostr(current_filepos.line);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Message(parser_e_methode_id_expected);
|
||||
{ recover by making it a normal procedure instead of method }
|
||||
aclass:=nil;
|
||||
end;
|
||||
end
|
||||
else
|
||||
Message(parser_e_class_id_expected);
|
||||
until not searchagain;
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
@ -3230,19 +3230,28 @@ implementation
|
||||
var
|
||||
s : string;
|
||||
t : ttoken;
|
||||
tmp: tobjectdef;
|
||||
begin
|
||||
{$ifdef EXTDEBUG}
|
||||
showhidden:=true;
|
||||
{$endif EXTDEBUG}
|
||||
s:='';
|
||||
if owner.symtabletype=localsymtable then
|
||||
s:=s+'local ';
|
||||
if assigned(_class) then
|
||||
begin
|
||||
if po_classmethod in procoptions then
|
||||
s:=s+'class ';
|
||||
s:=s+_class.objrealname^+'.';
|
||||
tmp:=_class;
|
||||
while assigned(tmp) do
|
||||
begin
|
||||
s:=tmp.objrealname^+'.'+s;
|
||||
if assigned(tmp.owner) and (tmp.owner.symtabletype=ObjectSymtable) then
|
||||
tmp:=tobjectdef(tmp.owner.defowner)
|
||||
else
|
||||
tmp:=nil;
|
||||
end;
|
||||
if (po_classmethod in procoptions) then
|
||||
s:='class ' + s;
|
||||
end;
|
||||
if owner.symtabletype=localsymtable then
|
||||
s:='local ' + s;
|
||||
if proctypeoption=potype_operator then
|
||||
begin
|
||||
for t:=NOTOKEN to last_overloaded do
|
||||
|
||||
64
tests/test/tclass11a.pp
Normal file
64
tests/test/tclass11a.pp
Normal file
@ -0,0 +1,64 @@
|
||||
program tclass11a;
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
{$apptype console}
|
||||
|
||||
type
|
||||
TSomeClass = class
|
||||
strict private
|
||||
type
|
||||
TPrivateNestedClass = class
|
||||
public
|
||||
procedure DoSomething;
|
||||
end;
|
||||
public
|
||||
type
|
||||
TNestedClass = class
|
||||
public
|
||||
procedure DoSomething;
|
||||
end;
|
||||
class procedure Test; virtual;
|
||||
end;
|
||||
|
||||
TDescendant = class(TSomeClass)
|
||||
public
|
||||
class procedure Test; override;
|
||||
end;
|
||||
|
||||
procedure TSomeClass.TPrivateNestedClass.DoSomething;
|
||||
begin
|
||||
WriteLn('TSomeClass.TPrivateNestedClass.DoSomething: ok');
|
||||
end;
|
||||
|
||||
procedure TSomeClass.TNestedClass.DoSomething;
|
||||
begin
|
||||
WriteLn('TSomeClass.TNestedClass.DoSomething: ok');
|
||||
end;
|
||||
|
||||
class procedure TSomeClass.Test;
|
||||
var
|
||||
P: TPrivateNestedClass;
|
||||
N: TNestedClass;
|
||||
begin
|
||||
P := TPrivateNestedClass.Create;
|
||||
P.DoSomething;
|
||||
P.Free;
|
||||
N := TNestedClass.Create;
|
||||
N.DoSomething;
|
||||
N.Free;
|
||||
end;
|
||||
|
||||
class procedure TDescendant.Test;
|
||||
var
|
||||
N: TNestedClass;
|
||||
begin
|
||||
N := TNestedClass.Create;
|
||||
N.DoSomething;
|
||||
N.Free;
|
||||
end;
|
||||
|
||||
begin
|
||||
TSomeClass.Test;
|
||||
TDescendant.Test;
|
||||
end.
|
||||
70
tests/test/tclass11b.pp
Normal file
70
tests/test/tclass11b.pp
Normal file
@ -0,0 +1,70 @@
|
||||
{ %FAIL}
|
||||
program tclass11b;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
{$apptype console}
|
||||
|
||||
type
|
||||
TSomeClass = class
|
||||
strict private
|
||||
type
|
||||
TPrivateNestedClass = class
|
||||
public
|
||||
procedure DoSomething;
|
||||
end;
|
||||
public
|
||||
type
|
||||
TNestedClass = class
|
||||
public
|
||||
procedure DoSomething;
|
||||
end;
|
||||
class procedure Test; virtual;
|
||||
end;
|
||||
|
||||
TDescendant = class(TSomeClass)
|
||||
public
|
||||
class procedure Test; override;
|
||||
end;
|
||||
|
||||
procedure TSomeClass.TPrivateNestedClass.DoSomething;
|
||||
begin
|
||||
WriteLn('TSomeClass.TPrivateNestedClass.DoSomething: ok');
|
||||
end;
|
||||
|
||||
procedure TSomeClass.TNestedClass.DoSomething;
|
||||
begin
|
||||
WriteLn('TSomeClass.TNestedClass.DoSomething: ok');
|
||||
end;
|
||||
|
||||
class procedure TSomeClass.Test;
|
||||
var
|
||||
P: TPrivateNestedClass;
|
||||
N: TNestedClass;
|
||||
begin
|
||||
P := TPrivateNestedClass.Create;
|
||||
P.DoSomething;
|
||||
P.Free;
|
||||
N := TNestedClass.Create;
|
||||
N.DoSomething;
|
||||
N.Free;
|
||||
end;
|
||||
|
||||
class procedure TDescendant.Test;
|
||||
var
|
||||
P: TPrivateNestedClass;
|
||||
N: TNestedClass;
|
||||
begin
|
||||
P := TPrivateNestedClass.Create;
|
||||
P.DoSomething;
|
||||
P.Free;
|
||||
N := TNestedClass.Create;
|
||||
N.DoSomething;
|
||||
N.Free;
|
||||
end;
|
||||
|
||||
begin
|
||||
TSomeClass.Test;
|
||||
TDescendant.Test;
|
||||
end.
|
||||
Loading…
Reference in New Issue
Block a user