mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 11:26:33 +02:00
fcl-passrc: TPasClassType and TPasRecordType now have common ancestor, resolver: started advancedrecord methods
git-svn-id: trunk@40591 -
This commit is contained in:
parent
883f832263
commit
0043b747c7
@ -134,7 +134,7 @@ const
|
|||||||
nFoundCallCandidateX = 3057;
|
nFoundCallCandidateX = 3057;
|
||||||
nTextAfterFinalIgnored = 3058;
|
nTextAfterFinalIgnored = 3058;
|
||||||
nNoMemberIsProvidedToAccessProperty = 3059;
|
nNoMemberIsProvidedToAccessProperty = 3059;
|
||||||
// free 3060
|
nTheUseOfXisNotAllowedInARecord = 3060;
|
||||||
// free 3061
|
// free 3061
|
||||||
// free 3062
|
// free 3062
|
||||||
// free 3063
|
// free 3063
|
||||||
@ -251,6 +251,7 @@ resourcestring
|
|||||||
sFoundCallCandidateX = 'Found call candidate %s';
|
sFoundCallCandidateX = 'Found call candidate %s';
|
||||||
sTextAfterFinalIgnored = 'Text after final ''end.''. ignored by compiler';
|
sTextAfterFinalIgnored = 'Text after final ''end.''. ignored by compiler';
|
||||||
sNoMemberIsProvidedToAccessProperty = 'No member is provided to access property';
|
sNoMemberIsProvidedToAccessProperty = 'No member is provided to access property';
|
||||||
|
sTheUseOfXisNotAllowedInARecord = 'The use of "%s" is not allowed in a record';
|
||||||
sSymbolXIsNotPortable = 'Symbol "%s" is not portable';
|
sSymbolXIsNotPortable = 'Symbol "%s" is not portable';
|
||||||
sSymbolXIsExperimental = 'Symbol "%s" is experimental';
|
sSymbolXIsExperimental = 'Symbol "%s" is experimental';
|
||||||
sSymbolXIsNotImplemented = 'Symbol "%s" is not implemented';
|
sSymbolXIsNotImplemented = 'Symbol "%s" is not implemented';
|
||||||
|
@ -216,14 +216,24 @@ Works:
|
|||||||
- pass as arg doit(procedure begin end)
|
- pass as arg doit(procedure begin end)
|
||||||
- modifiers assembler varargs cdecl
|
- modifiers assembler varargs cdecl
|
||||||
- typecast
|
- typecast
|
||||||
|
- with
|
||||||
|
- self
|
||||||
- built-in procedure Val(const s: string; var e: enumtype; out Code: integertype);
|
- built-in procedure Val(const s: string; var e: enumtype; out Code: integertype);
|
||||||
|
|
||||||
ToDo:
|
ToDo:
|
||||||
- anonymous methods:
|
- operator overload
|
||||||
- with
|
- operator enumerator
|
||||||
- self
|
- binaryexpr
|
||||||
|
- advanced records:
|
||||||
|
- $modeswitch AdvancedRecords
|
||||||
|
- sub type
|
||||||
|
- const
|
||||||
|
- var
|
||||||
|
- function/procedure/class function/class procedure
|
||||||
|
- property, class property
|
||||||
|
- RTTI
|
||||||
|
- operator overloading
|
||||||
- Include/Exclude for set of int/char/bool
|
- Include/Exclude for set of int/char/bool
|
||||||
- set of CharRange
|
|
||||||
- error if property method resolution is not used
|
- error if property method resolution is not used
|
||||||
- $H-hintpos$H+
|
- $H-hintpos$H+
|
||||||
- $pop, $push
|
- $pop, $push
|
||||||
@ -235,13 +245,12 @@ ToDo:
|
|||||||
- proc: check if forward and impl default values match
|
- proc: check if forward and impl default values match
|
||||||
- call array of proc without ()
|
- call array of proc without ()
|
||||||
- attributes
|
- attributes
|
||||||
- object
|
|
||||||
- type helpers
|
- type helpers
|
||||||
- record/class helpers
|
- record/class helpers
|
||||||
|
- array of const
|
||||||
- generics, nested param lists
|
- generics, nested param lists
|
||||||
|
- object
|
||||||
- futures
|
- futures
|
||||||
- operator overload
|
|
||||||
- operator enumerator
|
|
||||||
- TPasFileType
|
- TPasFileType
|
||||||
- labels
|
- labels
|
||||||
- $zerobasedstrings on|off
|
- $zerobasedstrings on|off
|
||||||
@ -838,9 +847,16 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TPasClassOrRecordScope }
|
||||||
|
|
||||||
|
TPasClassOrRecordScope = Class(TPasIdentifierScope)
|
||||||
|
public
|
||||||
|
DefaultProperty: TPasProperty;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TPasRecordScope }
|
{ TPasRecordScope }
|
||||||
|
|
||||||
TPasRecordScope = Class(TPasIdentifierScope)
|
TPasRecordScope = Class(TPasClassOrRecordScope)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TPasClassScopeFlag = (
|
TPasClassScopeFlag = (
|
||||||
@ -863,12 +879,11 @@ type
|
|||||||
|
|
||||||
{ TPasClassScope }
|
{ TPasClassScope }
|
||||||
|
|
||||||
TPasClassScope = Class(TPasIdentifierScope)
|
TPasClassScope = Class(TPasClassOrRecordScope)
|
||||||
public
|
public
|
||||||
AncestorScope: TPasClassScope;
|
AncestorScope: TPasClassScope;
|
||||||
CanonicalClassOf: TPasClassOfType;
|
CanonicalClassOf: TPasClassOfType;
|
||||||
DirectAncestor: TPasType; // TPasClassType or TPasAliasType, see GetPasClassAncestor
|
DirectAncestor: TPasType; // TPasClassType or TPasAliasType, see GetPasClassAncestor
|
||||||
DefaultProperty: TPasProperty;
|
|
||||||
Flags: TPasClassScopeFlags;
|
Flags: TPasClassScopeFlags;
|
||||||
AbstractProcs: TArrayOfPasProcedure;
|
AbstractProcs: TArrayOfPasProcedure;
|
||||||
Interfaces: TFPList; // list corresponds to TPasClassType(Element).Interfaces,
|
Interfaces: TFPList; // list corresponds to TPasClassType(Element).Interfaces,
|
||||||
@ -894,7 +909,7 @@ type
|
|||||||
DeclarationProc: TPasProcedure; // the corresponding forward declaration
|
DeclarationProc: TPasProcedure; // the corresponding forward declaration
|
||||||
ImplProc: TPasProcedure; // the corresponding proc with Body
|
ImplProc: TPasProcedure; // the corresponding proc with Body
|
||||||
OverriddenProc: TPasProcedure; // if IsOverride then this is the ancestor proc (virtual or override)
|
OverriddenProc: TPasProcedure; // if IsOverride then this is the ancestor proc (virtual or override)
|
||||||
ClassScope: TPasClassScope;
|
ClassScope: TPasClassOrRecordScope;
|
||||||
SelfArg: TPasArgument;
|
SelfArg: TPasArgument;
|
||||||
Flags: TPasProcedureScopeFlags;
|
Flags: TPasProcedureScopeFlags;
|
||||||
BoolSwitches: TBoolSwitches; // if Body<>nil then body start, otherwise when FinishProc
|
BoolSwitches: TBoolSwitches; // if Body<>nil then body start, otherwise when FinishProc
|
||||||
@ -1424,7 +1439,7 @@ type
|
|||||||
procedure FinishWithDo(El: TPasImplWithDo); virtual;
|
procedure FinishWithDo(El: TPasImplWithDo); virtual;
|
||||||
procedure FinishDeclaration(El: TPasElement); virtual;
|
procedure FinishDeclaration(El: TPasElement); virtual;
|
||||||
procedure FinishVariable(El: TPasVariable); virtual;
|
procedure FinishVariable(El: TPasVariable); virtual;
|
||||||
procedure FinishPropertyOfClass(PropEl: TPasProperty); virtual;
|
procedure FinishProperty(PropEl: TPasProperty); virtual;
|
||||||
procedure FinishArgument(El: TPasArgument); virtual;
|
procedure FinishArgument(El: TPasArgument); virtual;
|
||||||
procedure FinishAncestors(aClass: TPasClassType); virtual;
|
procedure FinishAncestors(aClass: TPasClassType); virtual;
|
||||||
procedure FinishMethodResolution(El: TPasMethodResolution); virtual;
|
procedure FinishMethodResolution(El: TPasMethodResolution); virtual;
|
||||||
@ -4298,7 +4313,7 @@ begin
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
// give a hint
|
// give a hint
|
||||||
if Data^.Proc.Parent is TPasClassType then
|
if Data^.Proc.Parent is TPasMembersType then
|
||||||
LogMsg(20171118205344,mtHint,nFunctionHidesIdentifier_NonProc,sFunctionHidesIdentifier,
|
LogMsg(20171118205344,mtHint,nFunctionHidesIdentifier_NonProc,sFunctionHidesIdentifier,
|
||||||
[GetElementSourcePosStr(El)],Data^.Proc.ProcType);
|
[GetElementSourcePosStr(El)],Data^.Proc.ProcType);
|
||||||
end;
|
end;
|
||||||
@ -4397,7 +4412,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
// Delphi/FPC do not give a message when hiding a non virtual method
|
// Delphi/FPC do not give a message when hiding a non virtual method
|
||||||
// -> emit Hint with other message id
|
// -> emit Hint with other message id
|
||||||
if (Data^.Proc.Parent is TPasClassType) then
|
if (Data^.Proc.Parent is TPasMembersType) then
|
||||||
begin
|
begin
|
||||||
ProcScope:=Proc.CustomData as TPasProcedureScope;
|
ProcScope:=Proc.CustomData as TPasProcedureScope;
|
||||||
if (ProcScope.ImplProc<>nil) // not abstract, external
|
if (ProcScope.ImplProc<>nil) // not abstract, external
|
||||||
@ -4920,7 +4935,7 @@ begin
|
|||||||
else if (C=TPasAliasType) or (C=TPasTypeAliasType) then
|
else if (C=TPasAliasType) or (C=TPasTypeAliasType) then
|
||||||
begin
|
begin
|
||||||
aType:=ResolveAliasType(El);
|
aType:=ResolveAliasType(El);
|
||||||
if (aType is TPasClassType) and (aType.CustomData=nil) then
|
if (aType is TPasMembersType) and (aType.CustomData=nil) then
|
||||||
exit;
|
exit;
|
||||||
EmitTypeHints(El,TPasAliasType(El).DestType);
|
EmitTypeHints(El,TPasAliasType(El).DestType);
|
||||||
end
|
end
|
||||||
@ -5423,6 +5438,22 @@ begin
|
|||||||
if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
|
if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
|
||||||
RaiseMsg(20170216151631,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'static'],Proc);
|
RaiseMsg(20170216151631,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'static'],Proc);
|
||||||
end
|
end
|
||||||
|
else if Proc.Parent is TPasRecordType then
|
||||||
|
begin
|
||||||
|
if Proc.IsReintroduced then
|
||||||
|
RaiseMsg(20181218195735,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'reintroduce'],Proc);
|
||||||
|
if Proc.IsVirtual then
|
||||||
|
RaiseMsg(20181218195431,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'virtual'],Proc);
|
||||||
|
if Proc.IsOverride then
|
||||||
|
RaiseMsg(20181218195437,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'override'],Proc);
|
||||||
|
if Proc.IsAbstract then
|
||||||
|
RaiseMsg(20181218195552,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'abstract'],Proc);
|
||||||
|
if Proc.IsForward then
|
||||||
|
RaiseMsg(20181218195514,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'forward'],Proc);
|
||||||
|
if Proc.IsStatic then
|
||||||
|
if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
|
||||||
|
RaiseMsg(20181218195519,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'static'],Proc);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
// intf proc, forward proc, proc body, method body, anonymous proc
|
// intf proc, forward proc, proc body, method body, anonymous proc
|
||||||
@ -5466,7 +5497,7 @@ begin
|
|||||||
if Proc.LibrarySymbolName<>nil then
|
if Proc.LibrarySymbolName<>nil then
|
||||||
ResolveExpr(Proc.LibrarySymbolName,rraRead);
|
ResolveExpr(Proc.LibrarySymbolName,rraRead);
|
||||||
|
|
||||||
if Proc.Parent is TPasClassType then
|
if Proc.Parent is TPasMembersType then
|
||||||
begin
|
begin
|
||||||
FinishMethodDeclHeader(Proc);
|
FinishMethodDeclHeader(Proc);
|
||||||
exit;
|
exit;
|
||||||
@ -5581,7 +5612,7 @@ procedure TPasResolver.FinishMethodDeclHeader(Proc: TPasProcedure);
|
|||||||
|
|
||||||
var
|
var
|
||||||
Abort: boolean;
|
Abort: boolean;
|
||||||
ClassScope: TPasClassScope;
|
ClassOrRecScope: TPasClassOrRecordScope;
|
||||||
FindData: TFindOverloadProcData;
|
FindData: TFindOverloadProcData;
|
||||||
OverloadProc: TPasProcedure;
|
OverloadProc: TPasProcedure;
|
||||||
ProcScope: TPasProcedureScope;
|
ProcScope: TPasProcedureScope;
|
||||||
@ -5591,14 +5622,14 @@ begin
|
|||||||
ProcScope:=TopScope as TPasProcedureScope;
|
ProcScope:=TopScope as TPasProcedureScope;
|
||||||
// ToDo: store the scanner flags *before* it has parsed the token after the proc
|
// ToDo: store the scanner flags *before* it has parsed the token after the proc
|
||||||
StoreScannerFlagsInProc(ProcScope);
|
StoreScannerFlagsInProc(ProcScope);
|
||||||
ClassScope:=Scopes[ScopeCount-2] as TPasClassScope;
|
ClassOrRecScope:=Scopes[ScopeCount-2] as TPasClassOrRecordScope;
|
||||||
ProcScope.ClassScope:=ClassScope;
|
ProcScope.ClassScope:=ClassOrRecScope;
|
||||||
FindData:=Default(TFindOverloadProcData);
|
FindData:=Default(TFindOverloadProcData);
|
||||||
FindData.Proc:=Proc;
|
FindData.Proc:=Proc;
|
||||||
FindData.Args:=Proc.ProcType.Args;
|
FindData.Args:=Proc.ProcType.Args;
|
||||||
FindData.Kind:=fopkMethod;
|
FindData.Kind:=fopkMethod;
|
||||||
Abort:=false;
|
Abort:=false;
|
||||||
ClassScope.IterateElements(Proc.Name,ClassScope,@OnFindOverloadProc,@FindData,Abort);
|
ClassOrRecScope.IterateElements(Proc.Name,ClassOrRecScope,@OnFindOverloadProc,@FindData,Abort);
|
||||||
|
|
||||||
if FindData.Found=nil then
|
if FindData.Found=nil then
|
||||||
begin
|
begin
|
||||||
@ -5643,24 +5674,25 @@ begin
|
|||||||
if proFixCaseOfOverrides in Options then
|
if proFixCaseOfOverrides in Options then
|
||||||
Proc.Name:=OverloadProc.Name;
|
Proc.Name:=OverloadProc.Name;
|
||||||
// remove abstract
|
// remove abstract
|
||||||
if OverloadProc.IsAbstract then
|
if OverloadProc.IsAbstract and (ClassOrRecScope is TPasClassScope) then
|
||||||
for i:=length(ClassScope.AbstractProcs)-1 downto 0 do
|
for i:=length(TPasClassScope(ClassOrRecScope).AbstractProcs)-1 downto 0 do
|
||||||
if ClassScope.AbstractProcs[i]=OverloadProc then
|
if TPasClassScope(ClassOrRecScope).AbstractProcs[i]=OverloadProc then
|
||||||
Delete(ClassScope.AbstractProcs,i,1);
|
Delete(TPasClassScope(ClassOrRecScope).AbstractProcs,i,1);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
// add abstract
|
// add abstract
|
||||||
if Proc.IsAbstract then
|
if Proc.IsAbstract and (ClassOrRecScope is TPasClassScope) then
|
||||||
Insert(Proc,ClassScope.AbstractProcs,length(ClassScope.AbstractProcs));
|
Insert(Proc,TPasClassScope(ClassOrRecScope).AbstractProcs,
|
||||||
|
length(TPasClassScope(ClassOrRecScope).AbstractProcs));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.FinishMethodImplHeader(ImplProc: TPasProcedure);
|
procedure TPasResolver.FinishMethodImplHeader(ImplProc: TPasProcedure);
|
||||||
var
|
var
|
||||||
ProcName: String;
|
ProcName: String;
|
||||||
CurClassType: TPasClassType;
|
ClassRecType: TPasMembersType;
|
||||||
ImplProcScope, DeclProcScope: TPasProcedureScope;
|
ImplProcScope, DeclProcScope: TPasProcedureScope;
|
||||||
DeclProc: TPasProcedure;
|
DeclProc: TPasProcedure;
|
||||||
CurClassScope: TPasClassScope;
|
CurClassRecScope: TPasClassOrRecordScope;
|
||||||
SelfArg: TPasArgument;
|
SelfArg: TPasArgument;
|
||||||
p: Integer;
|
p: Integer;
|
||||||
begin
|
begin
|
||||||
@ -5685,14 +5717,14 @@ begin
|
|||||||
if not IsValidIdent(ProcName) then
|
if not IsValidIdent(ProcName) then
|
||||||
RaiseNotYetImplemented(20160922163421,ImplProc.ProcType);
|
RaiseNotYetImplemented(20160922163421,ImplProc.ProcType);
|
||||||
|
|
||||||
// search proc in class
|
// search proc in class/record
|
||||||
ImplProcScope:=ImplProc.CustomData as TPasProcedureScope;
|
ImplProcScope:=ImplProc.CustomData as TPasProcedureScope;
|
||||||
CurClassScope:=ImplProcScope.ClassScope;
|
CurClassRecScope:=ImplProcScope.ClassScope;
|
||||||
if CurClassScope=nil then
|
if CurClassRecScope=nil then
|
||||||
RaiseInternalError(20161013172346);
|
RaiseInternalError(20161013172346);
|
||||||
CurClassType:=NoNil(CurClassScope.Element) as TPasClassType;
|
ClassRecType:=NoNil(CurClassRecScope.Element) as TPasMembersType;
|
||||||
|
|
||||||
DeclProc:=FindProcOverload(ProcName,ImplProc,CurClassScope);
|
DeclProc:=FindProcOverload(ProcName,ImplProc,CurClassRecScope);
|
||||||
if DeclProc=nil then
|
if DeclProc=nil then
|
||||||
RaiseIdentifierNotFound(20170216151720,ImplProc.Name,ImplProc.ProcType);
|
RaiseIdentifierNotFound(20170216151720,ImplProc.Name,ImplProc.ProcType);
|
||||||
DeclProcScope:=DeclProc.CustomData as TPasProcedureScope;
|
DeclProcScope:=DeclProc.CustomData as TPasProcedureScope;
|
||||||
@ -5721,14 +5753,14 @@ begin
|
|||||||
or (DeclProc.ClassType=TPasClassProcedure)
|
or (DeclProc.ClassType=TPasClassProcedure)
|
||||||
or (DeclProc.ClassType=TPasClassFunction) then
|
or (DeclProc.ClassType=TPasClassFunction) then
|
||||||
begin
|
begin
|
||||||
if not DeclProc.IsStatic then
|
if (not DeclProc.IsStatic) and (CurClassRecScope is TPasClassScope) then
|
||||||
begin
|
begin
|
||||||
// 'Self' in a class proc is the hidden classtype argument
|
// 'Self' in a class proc is the hidden classtype argument
|
||||||
SelfArg:=TPasArgument.Create('Self',DeclProc);
|
SelfArg:=TPasArgument.Create('Self',DeclProc);
|
||||||
ImplProcScope.SelfArg:=SelfArg;
|
ImplProcScope.SelfArg:=SelfArg;
|
||||||
{$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
|
{$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
|
||||||
SelfArg.Access:=argConst;
|
SelfArg.Access:=argConst;
|
||||||
SelfArg.ArgType:=CurClassScope.CanonicalClassOf;
|
SelfArg.ArgType:=TPasClassScope(CurClassRecScope).CanonicalClassOf;
|
||||||
SelfArg.ArgType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
|
SelfArg.ArgType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
|
||||||
AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
|
AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
|
||||||
end;
|
end;
|
||||||
@ -5740,8 +5772,8 @@ begin
|
|||||||
ImplProcScope.SelfArg:=SelfArg;
|
ImplProcScope.SelfArg:=SelfArg;
|
||||||
{$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
|
{$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
|
||||||
SelfArg.Access:=argConst;
|
SelfArg.Access:=argConst;
|
||||||
SelfArg.ArgType:=CurClassType;
|
SelfArg.ArgType:=ClassRecType;
|
||||||
CurClassType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
|
ClassRecType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
|
||||||
AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
|
AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -5783,7 +5815,7 @@ begin
|
|||||||
if (C=TPasVariable) or (C=TPasConst) then
|
if (C=TPasVariable) or (C=TPasConst) then
|
||||||
FinishVariable(TPasVariable(El))
|
FinishVariable(TPasVariable(El))
|
||||||
else if C=TPasProperty then
|
else if C=TPasProperty then
|
||||||
FinishPropertyOfClass(TPasProperty(El))
|
FinishProperty(TPasProperty(El))
|
||||||
else if C=TPasArgument then
|
else if C=TPasArgument then
|
||||||
FinishArgument(TPasArgument(El))
|
FinishArgument(TPasArgument(El))
|
||||||
else if C=TPasMethodResolution then
|
else if C=TPasMethodResolution then
|
||||||
@ -5812,6 +5844,9 @@ begin
|
|||||||
ResolveExpr(El.Expr,rraRead);
|
ResolveExpr(El.Expr,rraRead);
|
||||||
if El.VarType<>nil then
|
if El.VarType<>nil then
|
||||||
begin
|
begin
|
||||||
|
if (El.Parent is TPasRecordType) and (El.VarType=El.Parent) then
|
||||||
|
RaiseMsg(20181218173631,nTypeXIsNotYetCompletelyDefined,
|
||||||
|
sTypeXIsNotYetCompletelyDefined,[El.VarType.Name],El);
|
||||||
if El.Expr<>nil then
|
if El.Expr<>nil then
|
||||||
CheckAssignCompatibility(El,El.Expr,true);
|
CheckAssignCompatibility(El,El.Expr,true);
|
||||||
end
|
end
|
||||||
@ -5855,7 +5890,7 @@ begin
|
|||||||
EmitTypeHints(El,El.VarType);
|
EmitTypeHints(El,El.VarType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.FinishPropertyOfClass(PropEl: TPasProperty);
|
procedure TPasResolver.FinishProperty(PropEl: TPasProperty);
|
||||||
var
|
var
|
||||||
PropType: TPasType;
|
PropType: TPasType;
|
||||||
ClassScope: TPasClassScope;
|
ClassScope: TPasClassScope;
|
||||||
@ -6750,7 +6785,7 @@ begin
|
|||||||
CreateReference(IntfProc,Expr,rraRead);
|
CreateReference(IntfProc,Expr,rraRead);
|
||||||
if IntfProc.ClassType<>El.ProcClass then
|
if IntfProc.ClassType<>El.ProcClass then
|
||||||
RaiseXExpectedButYFound(20180323144107,GetElementTypeName(El.ProcClass),GetElementTypeName(IntfProc),El.InterfaceProc);
|
RaiseXExpectedButYFound(20180323144107,GetElementTypeName(El.ProcClass),GetElementTypeName(IntfProc),El.InterfaceProc);
|
||||||
// Note: do not create map here. CheckImplements in FinishPropertyOfClass must be called before.
|
// Note: do not create map here. CheckImplements in FinishProperty must be called before.
|
||||||
|
|
||||||
// El.ImplementationProc is resolved in FinishClassType
|
// El.ImplementationProc is resolved in FinishClassType
|
||||||
end;
|
end;
|
||||||
@ -7863,7 +7898,7 @@ begin
|
|||||||
// identifier is a proc and args brackets are missing
|
// identifier is a proc and args brackets are missing
|
||||||
if El.Parent.ClassType=TPasProperty then
|
if El.Parent.ClassType=TPasProperty then
|
||||||
// a property accessor does not need args -> ok
|
// a property accessor does not need args -> ok
|
||||||
// Note: the detailed tests are in FinishPropertyOfClass
|
// Note: the detailed tests are in FinishProperty
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
// examples: funca or @proca or a.funca or @a.funca ...
|
// examples: funca or @proca or a.funca or @a.funca ...
|
||||||
@ -7936,7 +7971,8 @@ procedure TPasResolver.ResolveInherited(El: TInheritedExpr;
|
|||||||
Access: TResolvedRefAccess);
|
Access: TResolvedRefAccess);
|
||||||
var
|
var
|
||||||
ProcScope, DeclProcScope, SelfScope: TPasProcedureScope;
|
ProcScope, DeclProcScope, SelfScope: TPasProcedureScope;
|
||||||
AncestorScope, ClassScope: TPasClassScope;
|
AncestorScope: TPasClassScope;
|
||||||
|
ClassRecScope: TPasClassOrRecordScope;
|
||||||
DeclProc, AncestorProc: TPasProcedure;
|
DeclProc, AncestorProc: TPasProcedure;
|
||||||
begin
|
begin
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
@ -7955,13 +7991,24 @@ begin
|
|||||||
SelfScope:=ProcScope.GetSelfScope;
|
SelfScope:=ProcScope.GetSelfScope;
|
||||||
if SelfScope=nil then
|
if SelfScope=nil then
|
||||||
RaiseMsg(20170216152141,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
|
RaiseMsg(20170216152141,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
|
||||||
ClassScope:=SelfScope.ClassScope;
|
ClassRecScope:=SelfScope.ClassScope;
|
||||||
|
|
||||||
AncestorScope:=ClassScope.AncestorScope;
|
AncestorScope:=nil;
|
||||||
if AncestorScope=nil then
|
if ClassRecScope is TPasClassScope then
|
||||||
begin
|
begin
|
||||||
// 'inherited;' without ancestor class is silently ignored
|
// inherited in class method
|
||||||
exit;
|
AncestorScope:=TPasClassScope(ClassRecScope).AncestorScope;
|
||||||
|
if AncestorScope=nil then
|
||||||
|
begin
|
||||||
|
// 'inherited;' without ancestor class is silently ignored
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// inherited in record method
|
||||||
|
RaiseMsg(20181218194022,nTheUseOfXisNotAllowedInARecord,sTheUseOfXisNotAllowedInARecord,
|
||||||
|
['inherited'],El);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// search ancestor in element, i.e. 'inherited' expression
|
// search ancestor in element, i.e. 'inherited' expression
|
||||||
@ -7986,7 +8033,8 @@ procedure TPasResolver.ResolveInheritedCall(El: TBinaryExpr;
|
|||||||
// El.right is the identifier and parameters
|
// El.right is the identifier and parameters
|
||||||
var
|
var
|
||||||
ProcScope, SelfScope: TPasProcedureScope;
|
ProcScope, SelfScope: TPasProcedureScope;
|
||||||
AncestorScope, ClassScope: TPasClassScope;
|
AncestorScope: TPasClassScope;
|
||||||
|
ClassRecScope: TPasClassOrRecordScope;
|
||||||
AncestorClass: TPasClassType;
|
AncestorClass: TPasClassType;
|
||||||
InhScope: TPasDotClassScope;
|
InhScope: TPasDotClassScope;
|
||||||
begin
|
begin
|
||||||
@ -7998,11 +8046,22 @@ begin
|
|||||||
SelfScope:=ProcScope.GetSelfScope;
|
SelfScope:=ProcScope.GetSelfScope;
|
||||||
if SelfScope=nil then
|
if SelfScope=nil then
|
||||||
RaiseMsg(20170216152148,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
|
RaiseMsg(20170216152148,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
|
||||||
ClassScope:=SelfScope.ClassScope;
|
ClassRecScope:=SelfScope.ClassScope;
|
||||||
|
|
||||||
AncestorScope:=ClassScope.AncestorScope;
|
AncestorScope:=nil;
|
||||||
if AncestorScope=nil then
|
if ClassRecScope is TPasClassScope then
|
||||||
RaiseMsg(20170216152151,nInheritedNeedsAncestor,sInheritedNeedsAncestor,[],El.left);
|
begin
|
||||||
|
// inherited in class method
|
||||||
|
AncestorScope:=TPasClassScope(ClassRecScope).AncestorScope;
|
||||||
|
if AncestorScope=nil then
|
||||||
|
RaiseMsg(20170216152151,nInheritedNeedsAncestor,sInheritedNeedsAncestor,[],El.left);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// inherited in record method
|
||||||
|
RaiseMsg(20181218194436,nTheUseOfXisNotAllowedInARecord,sTheUseOfXisNotAllowedInARecord,
|
||||||
|
['inherited'],El);
|
||||||
|
end;
|
||||||
|
|
||||||
// search call in ancestor
|
// search call in ancestor
|
||||||
AncestorClass:=TPasClassType(AncestorScope.Element);
|
AncestorClass:=TPasClassType(AncestorScope.Element);
|
||||||
@ -9325,12 +9384,12 @@ procedure TPasResolver.AddProcedure(El: TPasProcedure);
|
|||||||
var
|
var
|
||||||
ProcName, aClassName: String;
|
ProcName, aClassName: String;
|
||||||
p: SizeInt;
|
p: SizeInt;
|
||||||
CurClassType: TPasClassType;
|
ClassOrRecType: TPasMembersType;
|
||||||
ProcScope: TPasProcedureScope;
|
ProcScope: TPasProcedureScope;
|
||||||
HasDot: Boolean;
|
HasDot: Boolean;
|
||||||
CurEl: TPasElement;
|
CurEl: TPasElement;
|
||||||
Identifier: TPasIdentifier;
|
Identifier: TPasIdentifier;
|
||||||
CurClassScope: TPasClassScope;
|
ClassOrRecScope: TPasClassOrRecordScope;
|
||||||
C: TClass;
|
C: TClass;
|
||||||
begin
|
begin
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
@ -9370,12 +9429,12 @@ begin
|
|||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
writeln('TPasResolver.AddProcedure searching class of "',ProcName,'" ...');
|
writeln('TPasResolver.AddProcedure searching class of "',ProcName,'" ...');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
CurClassType:=nil;
|
ClassOrRecType:=nil;
|
||||||
repeat
|
repeat
|
||||||
p:=Pos('.',ProcName);
|
p:=Pos('.',ProcName);
|
||||||
if p<1 then
|
if p<1 then
|
||||||
begin
|
begin
|
||||||
if CurClassType=nil then
|
if ClassOrRecType=nil then
|
||||||
RaiseInternalError(20161013170829);
|
RaiseInternalError(20161013170829);
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
@ -9387,10 +9446,10 @@ begin
|
|||||||
if not IsValidIdent(aClassName) then
|
if not IsValidIdent(aClassName) then
|
||||||
RaiseNotYetImplemented(20161013170844,El);
|
RaiseNotYetImplemented(20161013170844,El);
|
||||||
|
|
||||||
if CurClassType<>nil then
|
if ClassOrRecType<>nil then
|
||||||
begin
|
begin
|
||||||
CurClassScope:=TPasClassScope(CurClassType.CustomData);
|
ClassOrRecScope:=TPasClassOrRecordScope(ClassOrRecType.CustomData);
|
||||||
Identifier:=CurClassScope.FindLocalIdentifier(aClassName);
|
Identifier:=ClassOrRecScope.FindLocalIdentifier(aClassName);
|
||||||
if Identifier=nil then
|
if Identifier=nil then
|
||||||
RaiseIdentifierNotFound(20180430130635,aClassName,El);
|
RaiseIdentifierNotFound(20180430130635,aClassName,El);
|
||||||
CurEl:=Identifier.Element;
|
CurEl:=Identifier.Element;
|
||||||
@ -9398,7 +9457,7 @@ begin
|
|||||||
else
|
else
|
||||||
CurEl:=FindElementWithoutParams(aClassName,El,false);
|
CurEl:=FindElementWithoutParams(aClassName,El,false);
|
||||||
|
|
||||||
if not (CurEl is TPasClassType) then
|
if not (CurEl is TPasMembersType) then
|
||||||
begin
|
begin
|
||||||
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
@ -9407,26 +9466,29 @@ begin
|
|||||||
RaiseXExpectedButYFound(20170216152557,
|
RaiseXExpectedButYFound(20170216152557,
|
||||||
'class',aClassname+':'+GetElementTypeName(CurEl),El);
|
'class',aClassname+':'+GetElementTypeName(CurEl),El);
|
||||||
end;
|
end;
|
||||||
CurClassType:=TPasClassType(CurEl);
|
ClassOrRecType:=TPasMembersType(CurEl);
|
||||||
if CurClassType.ObjKind<>okClass then
|
if ClassOrRecType is TPasClassType then
|
||||||
begin
|
begin
|
||||||
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
if TPasClassType(ClassOrRecType).ObjKind<>okClass then
|
||||||
RaiseXExpectedButYFound(20180321161722,
|
begin
|
||||||
'class',aClassname+':'+GetElementTypeName(CurEl),El);
|
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
||||||
|
RaiseXExpectedButYFound(20180321161722,
|
||||||
|
'class',aClassname+':'+GetElementTypeName(CurEl),El);
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
if CurClassType.GetModule<>El.GetModule then
|
if ClassOrRecType.GetModule<>El.GetModule then
|
||||||
begin
|
begin
|
||||||
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
||||||
RaiseMsg(20180211230432,nMethodClassXInOtherUnitY,sMethodClassXInOtherUnitY,
|
RaiseMsg(20180211230432,nMethodClassXInOtherUnitY,sMethodClassXInOtherUnitY,
|
||||||
[aClassName,CurClassType.GetModule.Name],El);
|
[aClassName,ClassOrRecType.GetModule.Name],El);
|
||||||
end;
|
end;
|
||||||
until false;
|
until false;
|
||||||
|
|
||||||
if not IsValidIdent(ProcName) then
|
if not IsValidIdent(ProcName) then
|
||||||
RaiseNotYetImplemented(20161013170956,El);
|
RaiseNotYetImplemented(20161013170956,El);
|
||||||
|
|
||||||
ProcScope.VisibilityContext:=CurClassType;
|
ProcScope.VisibilityContext:=ClassOrRecType;
|
||||||
ProcScope.ClassScope:=NoNil(CurClassType.CustomData) as TPasClassScope;
|
ProcScope.ClassScope:=NoNil(ClassOrRecType.CustomData) as TPasClassOrRecordScope;
|
||||||
end;// HasDot=true
|
end;// HasDot=true
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -14576,8 +14638,9 @@ var
|
|||||||
OnlyTypeMembers, IsClassOf: Boolean;
|
OnlyTypeMembers, IsClassOf: Boolean;
|
||||||
TypeEl: TPasType;
|
TypeEl: TPasType;
|
||||||
C: TClass;
|
C: TClass;
|
||||||
ClassScope: TPasClassScope;
|
ClassRecScope: TPasClassOrRecordScope;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
AbstractProcs: TArrayOfPasProcedure;
|
||||||
begin
|
begin
|
||||||
StartScope:=FindData.StartScope;
|
StartScope:=FindData.StartScope;
|
||||||
OnlyTypeMembers:=false;
|
OnlyTypeMembers:=false;
|
||||||
@ -14694,25 +14757,29 @@ begin
|
|||||||
RaiseInternalError(20170131141936);
|
RaiseInternalError(20170131141936);
|
||||||
Ref.Context:=TResolvedRefCtxConstructor.Create;
|
Ref.Context:=TResolvedRefCtxConstructor.Create;
|
||||||
if StartScope is TPasDotClassScope then
|
if StartScope is TPasDotClassScope then
|
||||||
ClassScope:=TPasDotClassScope(StartScope).ClassScope
|
ClassRecScope:=TPasDotClassScope(StartScope).ClassScope
|
||||||
else if (StartScope is TPasWithExprScope)
|
else if (StartScope is TPasWithExprScope)
|
||||||
and (TPasWithExprScope(StartScope).Scope is TPasClassScope) then
|
and (TPasWithExprScope(StartScope).Scope is TPasClassOrRecordScope) then
|
||||||
ClassScope:=TPasClassScope(TPasWithExprScope(StartScope).Scope)
|
ClassRecScope:=TPasClassOrRecordScope(TPasWithExprScope(StartScope).Scope)
|
||||||
else if (StartScope is TPasProcedureScope) then
|
else if (StartScope is TPasProcedureScope) then
|
||||||
ClassScope:=TPasProcedureScope(StartScope).ClassScope
|
ClassRecScope:=TPasProcedureScope(StartScope).ClassScope
|
||||||
else
|
else
|
||||||
RaiseInternalError(20170131150855,GetObjName(StartScope));
|
RaiseInternalError(20170131150855,GetObjName(StartScope));
|
||||||
TypeEl:=ClassScope.Element as TPasType;
|
TypeEl:=ClassRecScope.Element as TPasType;
|
||||||
TResolvedRefCtxConstructor(Ref.Context).Typ:=TypeEl;
|
TResolvedRefCtxConstructor(Ref.Context).Typ:=TypeEl;
|
||||||
if (length(ClassScope.AbstractProcs)>0) then
|
if ClassRecScope is TPasClassScope then
|
||||||
begin
|
begin
|
||||||
if IsClassOf then
|
AbstractProcs:=TPasClassScope(ClassRecScope).AbstractProcs;
|
||||||
// aClass.Create: do not warn
|
if (length(AbstractProcs)>0) then
|
||||||
else
|
begin
|
||||||
for i:=0 to length(ClassScope.AbstractProcs)-1 do
|
if IsClassOf then
|
||||||
LogMsg(20171227110746,mtWarning,nConstructingClassXWithAbstractMethodY,
|
// aClass.Create: do not warn
|
||||||
sConstructingClassXWithAbstractMethodY,
|
else
|
||||||
[TypeEl.Name,ClassScope.AbstractProcs[i].Name],FindData.ErrorPosEl);
|
for i:=0 to length(AbstractProcs)-1 do
|
||||||
|
LogMsg(20171227110746,mtWarning,nConstructingClassXWithAbstractMethodY,
|
||||||
|
sConstructingClassXWithAbstractMethodY,
|
||||||
|
[TypeEl.Name,AbstractProcs[i].Name],FindData.ErrorPosEl);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
@ -20528,7 +20595,7 @@ var
|
|||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
if El=nil then exit;
|
if El=nil then exit;
|
||||||
if El.Parent is TPasClassType then exit(true);
|
if El.Parent is TPasMembersType then exit(true);
|
||||||
if not (El.CustomData is TPasProcedureScope) then exit;
|
if not (El.CustomData is TPasProcedureScope) then exit;
|
||||||
ProcScope:=TPasProcedureScope(El.CustomData);
|
ProcScope:=TPasProcedureScope(El.CustomData);
|
||||||
Result:=IsMethod(ProcScope.DeclarationProc);
|
Result:=IsMethod(ProcScope.DeclarationProc);
|
||||||
|
@ -692,14 +692,31 @@ type
|
|||||||
Members: TPasRecordType;
|
Members: TPasRecordType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TPasRecordType }
|
{ TPasMembersType - base type for TPasRecordType and TPasClassType }
|
||||||
|
|
||||||
TPasRecordType = class(TPasType)
|
TPasMembersType = class(TPasType)
|
||||||
private
|
private
|
||||||
procedure ClearChildReferences(El: TPasElement; arg: pointer);
|
procedure ClearChildReferences(El: TPasElement; arg: pointer);
|
||||||
procedure GetMembers(S: TStrings);
|
|
||||||
protected
|
protected
|
||||||
procedure SetParent(const AValue: TPasElement); override;
|
procedure SetParent(const AValue: TPasElement); override;
|
||||||
|
public
|
||||||
|
PackMode: TPackMode;
|
||||||
|
Members: TFPList;
|
||||||
|
GenericTemplateTypes: TFPList; // list of TPasGenericTemplateType
|
||||||
|
Constructor Create(const AName: string; AParent: TPasElement); override;
|
||||||
|
Destructor Destroy; override;
|
||||||
|
Function IsPacked: Boolean;
|
||||||
|
Function IsBitPacked : Boolean;
|
||||||
|
Procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
||||||
|
const Arg: Pointer); override;
|
||||||
|
Procedure SetGenericTemplates(AList: TFPList); virtual;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TPasRecordType }
|
||||||
|
|
||||||
|
TPasRecordType = class(TPasMembersType)
|
||||||
|
private
|
||||||
|
procedure GetMembers(S: TStrings);
|
||||||
public
|
public
|
||||||
constructor Create(const AName: string; AParent: TPasElement); override;
|
constructor Create(const AName: string; AParent: TPasElement); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -708,15 +725,9 @@ type
|
|||||||
procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
||||||
const Arg: Pointer); override;
|
const Arg: Pointer); override;
|
||||||
public
|
public
|
||||||
PackMode: TPackMode;
|
|
||||||
Members: TFPList; // list of TPasVariable elements
|
|
||||||
VariantEl: TPasElement; // nil or TPasVariable or TPasType
|
VariantEl: TPasElement; // nil or TPasVariable or TPasType
|
||||||
Variants: TFPList; // list of TPasVariant elements, may be nil!
|
Variants: TFPList; // list of TPasVariant elements, may be nil!
|
||||||
GenericTemplateTypes: TFPList; // list of TPasGenericTemplateType
|
|
||||||
Function IsPacked: Boolean;
|
|
||||||
Function IsBitPacked : Boolean;
|
|
||||||
Function IsAdvancedRecord : Boolean;
|
Function IsAdvancedRecord : Boolean;
|
||||||
Procedure SetGenericTemplates(AList : TFPList);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TPasGenericTemplateType = Class(TPasType);
|
TPasGenericTemplateType = Class(TPasType);
|
||||||
@ -734,9 +745,7 @@ type
|
|||||||
|
|
||||||
{ TPasClassType }
|
{ TPasClassType }
|
||||||
|
|
||||||
TPasClassType = class(TPasType)
|
TPasClassType = class(TPasMembersType)
|
||||||
private
|
|
||||||
procedure ClearChildReferences(El: TPasElement; arg: pointer);
|
|
||||||
protected
|
protected
|
||||||
procedure SetParent(const AValue: TPasElement); override;
|
procedure SetParent(const AValue: TPasElement); override;
|
||||||
public
|
public
|
||||||
@ -746,7 +755,6 @@ type
|
|||||||
procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
||||||
const Arg: Pointer); override;
|
const Arg: Pointer); override;
|
||||||
public
|
public
|
||||||
PackMode: TPackMode;
|
|
||||||
ObjKind: TPasObjKind;
|
ObjKind: TPasObjKind;
|
||||||
AncestorType: TPasType; // TPasClassType or TPasUnresolvedTypeRef or TPasAliasType or TPasTypeAliasType
|
AncestorType: TPasType; // TPasClassType or TPasUnresolvedTypeRef or TPasAliasType or TPasTypeAliasType
|
||||||
// Note: AncestorType can be nil even though it has a default ancestor
|
// Note: AncestorType can be nil even though it has a default ancestor
|
||||||
@ -755,25 +763,20 @@ type
|
|||||||
IsExternal : Boolean;
|
IsExternal : Boolean;
|
||||||
IsShortDefinition: Boolean;//class(anchestor); without end
|
IsShortDefinition: Boolean;//class(anchestor); without end
|
||||||
GUIDExpr : TPasExpr;
|
GUIDExpr : TPasExpr;
|
||||||
Members: TFPList; // list of TPasElement
|
|
||||||
Modifiers: TStringList;
|
Modifiers: TStringList;
|
||||||
Interfaces : TFPList; // list of TPasType
|
Interfaces : TFPList; // list of TPasType
|
||||||
GenericTemplateTypes: TFPList; // list of TPasGenericTemplateType
|
|
||||||
ExternalNameSpace : String;
|
ExternalNameSpace : String;
|
||||||
ExternalName : String;
|
ExternalName : String;
|
||||||
InterfaceType: TPasClassInterfaceType;
|
InterfaceType: TPasClassInterfaceType;
|
||||||
Procedure SetGenericTemplates(AList : TFPList);
|
Procedure SetGenericTemplates(AList : TFPList); override;
|
||||||
Function FindMember(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
|
Function FindMember(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
|
||||||
Function FindMemberInAncestors(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
|
Function FindMemberInAncestors(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
|
||||||
Function IsPacked : Boolean;
|
|
||||||
Function InterfaceGUID : string;
|
Function InterfaceGUID : string;
|
||||||
Function IsSealed : Boolean;
|
Function IsSealed : Boolean;
|
||||||
Function IsAbstract : Boolean;
|
Function IsAbstract : Boolean;
|
||||||
Function HasModifier(const aModifier: String): Boolean;
|
Function HasModifier(const aModifier: String): Boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TArgumentAccess = (argDefault, argConst, argVar, argOut, argConstRef);
|
TArgumentAccess = (argDefault, argConst, argVar, argOut, argConstRef);
|
||||||
|
|
||||||
{ TPasArgument }
|
{ TPasArgument }
|
||||||
@ -2948,22 +2951,12 @@ end;
|
|||||||
constructor TPasRecordType.Create(const AName: string; AParent: TPasElement);
|
constructor TPasRecordType.Create(const AName: string; AParent: TPasElement);
|
||||||
begin
|
begin
|
||||||
inherited Create(AName, AParent);
|
inherited Create(AName, AParent);
|
||||||
Members := TFPList.Create;
|
|
||||||
GenericTemplateTypes:=TFPList.Create;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TPasRecordType.Destroy;
|
destructor TPasRecordType.Destroy;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
for i := 0 to GenericTemplateTypes.Count - 1 do
|
|
||||||
TPasElement(GenericTemplateTypes[i]).Release{$IFDEF CheckPasTreeRefCount}('TPasRecordType.GenericTemplateTypes'){$ENDIF};
|
|
||||||
FreeAndNil(GenericTemplateTypes);
|
|
||||||
|
|
||||||
for i := 0 to Members.Count - 1 do
|
|
||||||
TPasVariable(Members[i]).Release{$IFDEF CheckPasTreeRefCount}('TPasRecordType.Members'){$ENDIF};
|
|
||||||
FreeAndNil(Members);
|
|
||||||
|
|
||||||
ReleaseAndNil(TPasElement(VariantEl){$IFDEF CheckPasTreeRefCount},'TPasRecordType.VariantEl'{$ENDIF});
|
ReleaseAndNil(TPasElement(VariantEl){$IFDEF CheckPasTreeRefCount},'TPasRecordType.VariantEl'{$ENDIF});
|
||||||
|
|
||||||
if Assigned(Variants) then
|
if Assigned(Variants) then
|
||||||
@ -2978,19 +2971,12 @@ end;
|
|||||||
|
|
||||||
{ TPasClassType }
|
{ TPasClassType }
|
||||||
|
|
||||||
procedure TPasClassType.ClearChildReferences(El: TPasElement; arg: pointer);
|
|
||||||
begin
|
|
||||||
El.ClearTypeReferences(Self);
|
|
||||||
if arg=nil then ;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TPasClassType.SetParent(const AValue: TPasElement);
|
procedure TPasClassType.SetParent(const AValue: TPasElement);
|
||||||
begin
|
begin
|
||||||
if (AValue=nil) and (Parent<>nil) then
|
if (AValue=nil) and (Parent<>nil) then
|
||||||
begin
|
begin
|
||||||
// parent is cleared
|
// parent is cleared
|
||||||
// -> clear all child references to this class (releasing loops)
|
// -> clear all references to this class (releasing loops)
|
||||||
ForEachCall(@ClearChildReferences,nil);
|
|
||||||
if AncestorType=Self then
|
if AncestorType=Self then
|
||||||
ReleaseAndNil(TPasElement(AncestorType){$IFDEF CheckPasTreeRefCount},'TPasClassType.AncestorType'{$ENDIF});
|
ReleaseAndNil(TPasElement(AncestorType){$IFDEF CheckPasTreeRefCount},'TPasClassType.AncestorType'{$ENDIF});
|
||||||
if HelperForType=Self then
|
if HelperForType=Self then
|
||||||
@ -3002,27 +2988,15 @@ end;
|
|||||||
constructor TPasClassType.Create(const AName: string; AParent: TPasElement);
|
constructor TPasClassType.Create(const AName: string; AParent: TPasElement);
|
||||||
begin
|
begin
|
||||||
inherited Create(AName, AParent);
|
inherited Create(AName, AParent);
|
||||||
PackMode:=pmNone; // 12/04/04 - Dave - Added
|
|
||||||
IsShortDefinition := False;
|
IsShortDefinition := False;
|
||||||
Members := TFPList.Create;
|
|
||||||
Modifiers := TStringList.Create;
|
Modifiers := TStringList.Create;
|
||||||
Interfaces:= TFPList.Create;
|
Interfaces:= TFPList.Create;
|
||||||
GenericTemplateTypes:=TFPList.Create;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TPasClassType.Destroy;
|
destructor TPasClassType.Destroy;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
El: TPasElement;
|
|
||||||
begin
|
begin
|
||||||
for i := 0 to Members.Count - 1 do
|
|
||||||
begin
|
|
||||||
El:=TPasElement(Members[i]);
|
|
||||||
El.Parent:=nil;
|
|
||||||
El.Release{$IFDEF CheckPasTreeRefCount}('TPasClassType.Members'){$ENDIF};
|
|
||||||
end;
|
|
||||||
FreeAndNil(Members);
|
|
||||||
|
|
||||||
for i := 0 to Interfaces.Count - 1 do
|
for i := 0 to Interfaces.Count - 1 do
|
||||||
TPasElement(Interfaces[i]).Release{$IFDEF CheckPasTreeRefCount}('TPasClassType.Interfaces'){$ENDIF};
|
TPasElement(Interfaces[i]).Release{$IFDEF CheckPasTreeRefCount}('TPasClassType.Interfaces'){$ENDIF};
|
||||||
FreeAndNil(Interfaces);
|
FreeAndNil(Interfaces);
|
||||||
@ -3030,9 +3004,6 @@ begin
|
|||||||
ReleaseAndNil(TPasElement(HelperForType){$IFDEF CheckPasTreeRefCount},'TPasClassType.HelperForType'{$ENDIF});
|
ReleaseAndNil(TPasElement(HelperForType){$IFDEF CheckPasTreeRefCount},'TPasClassType.HelperForType'{$ENDIF});
|
||||||
ReleaseAndNil(TPasElement(GUIDExpr){$IFDEF CheckPasTreeRefCount},'TPasClassType.GUIDExpr'{$ENDIF});
|
ReleaseAndNil(TPasElement(GUIDExpr){$IFDEF CheckPasTreeRefCount},'TPasClassType.GUIDExpr'{$ENDIF});
|
||||||
FreeAndNil(Modifiers);
|
FreeAndNil(Modifiers);
|
||||||
for i := 0 to GenericTemplateTypes.Count - 1 do
|
|
||||||
TPasElement(GenericTemplateTypes[i]).Release{$IFDEF CheckPasTreeRefCount}('TPasClassType.GenericTemplateTypes'){$ENDIF};
|
|
||||||
FreeAndNil(GenericTemplateTypes);
|
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3062,26 +3033,12 @@ begin
|
|||||||
ForEachChildCall(aMethodCall,Arg,TPasElement(Interfaces[i]),true);
|
ForEachChildCall(aMethodCall,Arg,TPasElement(Interfaces[i]),true);
|
||||||
ForEachChildCall(aMethodCall,Arg,HelperForType,true);
|
ForEachChildCall(aMethodCall,Arg,HelperForType,true);
|
||||||
ForEachChildCall(aMethodCall,Arg,GUIDExpr,false);
|
ForEachChildCall(aMethodCall,Arg,GUIDExpr,false);
|
||||||
for i:=0 to Members.Count-1 do
|
|
||||||
ForEachChildCall(aMethodCall,Arg,TPasElement(Members[i]),false);
|
|
||||||
for i:=0 to GenericTemplateTypes.Count-1 do
|
|
||||||
ForEachChildCall(aMethodCall,Arg,TPasElement(GenericTemplateTypes[i]),false);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasClassType.SetGenericTemplates(AList: TFPList);
|
procedure TPasClassType.SetGenericTemplates(AList: TFPList);
|
||||||
|
|
||||||
Var
|
|
||||||
I : Integer;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ObjKind:=okGeneric;
|
ObjKind:=okGeneric;
|
||||||
For I:=0 to AList.Count-1 do
|
inherited SetGenericTemplates(AList);
|
||||||
begin
|
|
||||||
TPasElement(AList[i]).Parent:=Self;
|
|
||||||
GenericTemplateTypes.Add(AList[i]);
|
|
||||||
end;
|
|
||||||
AList.Clear;
|
|
||||||
ObjKind:=okGeneric;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasClassType.FindMember(MemberClass: TPTreeElement; const MemberName: String): TPasElement;
|
function TPasClassType.FindMember(MemberClass: TPTreeElement; const MemberName: String): TPasElement;
|
||||||
@ -3155,12 +3112,6 @@ begin
|
|||||||
Result:=false;
|
Result:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasClassType.IsPacked: Boolean;
|
|
||||||
begin
|
|
||||||
Result:=PackMode<>pmNone;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{ TPasArgument }
|
{ TPasArgument }
|
||||||
|
|
||||||
destructor TPasArgument.Destroy;
|
destructor TPasArgument.Destroy;
|
||||||
@ -3987,12 +3938,95 @@ begin
|
|||||||
ForEachChildCall(aMethodCall,Arg,EnumType,true);
|
ForEachChildCall(aMethodCall,Arg,EnumType,true);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasRecordType.ClearChildReferences(El: TPasElement; arg: pointer);
|
{ TPasMembersType }
|
||||||
|
|
||||||
|
procedure TPasMembersType.ClearChildReferences(El: TPasElement; arg: pointer);
|
||||||
begin
|
begin
|
||||||
El.ClearTypeReferences(Self);
|
El.ClearTypeReferences(Self);
|
||||||
if arg=nil then ;
|
if arg=nil then ;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPasMembersType.SetParent(const AValue: TPasElement);
|
||||||
|
begin
|
||||||
|
if (AValue=nil) and (Parent<>nil) then
|
||||||
|
begin
|
||||||
|
// parent is cleared
|
||||||
|
// -> clear all child references to this class/record (releasing loops)
|
||||||
|
ForEachCall(@ClearChildReferences,nil);
|
||||||
|
end;
|
||||||
|
inherited SetParent(AValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TPasMembersType.Create(const AName: string; AParent: TPasElement);
|
||||||
|
begin
|
||||||
|
inherited Create(AName, AParent);
|
||||||
|
PackMode:=pmNone;
|
||||||
|
Members := TFPList.Create;
|
||||||
|
GenericTemplateTypes:=TFPList.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TPasMembersType.Destroy;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
El: TPasElement;
|
||||||
|
begin
|
||||||
|
for i := 0 to Members.Count - 1 do
|
||||||
|
begin
|
||||||
|
El:=TPasElement(Members[i]);
|
||||||
|
El.Parent:=nil;
|
||||||
|
El.Release{$IFDEF CheckPasTreeRefCount}('TPasMembersType.Members'){$ENDIF};
|
||||||
|
end;
|
||||||
|
FreeAndNil(Members);
|
||||||
|
|
||||||
|
for i := 0 to GenericTemplateTypes.Count - 1 do
|
||||||
|
begin
|
||||||
|
El:=TPasElement(GenericTemplateTypes[i]);
|
||||||
|
El.Parent:=nil;
|
||||||
|
El.Release{$IFDEF CheckPasTreeRefCount}('TPasMembersType.GenericTemplateTypes'){$ENDIF};
|
||||||
|
end;
|
||||||
|
FreeAndNil(GenericTemplateTypes);
|
||||||
|
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPasMembersType.IsPacked: Boolean;
|
||||||
|
begin
|
||||||
|
Result:=(PackMode <> pmNone);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPasMembersType.IsBitPacked: Boolean;
|
||||||
|
begin
|
||||||
|
Result:=(PackMode=pmBitPacked)
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPasMembersType.ForEachCall(const aMethodCall: TOnForEachPasElement;
|
||||||
|
const Arg: Pointer);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
inherited ForEachCall(aMethodCall, Arg);
|
||||||
|
for i:=0 to GenericTemplateTypes.Count-1 do
|
||||||
|
ForEachChildCall(aMethodCall,Arg,TPasElement(GenericTemplateTypes[i]),true);
|
||||||
|
for i:=0 to Members.Count-1 do
|
||||||
|
ForEachChildCall(aMethodCall,Arg,TPasElement(Members[i]),false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPasMembersType.SetGenericTemplates(AList: TFPList);
|
||||||
|
var
|
||||||
|
I: Integer;
|
||||||
|
El: TPasElement;
|
||||||
|
begin
|
||||||
|
For I:=0 to AList.Count-1 do
|
||||||
|
begin
|
||||||
|
El:=TPasElement(AList[i]);
|
||||||
|
El.Parent:=Self;
|
||||||
|
GenericTemplateTypes.Add(El);
|
||||||
|
end;
|
||||||
|
AList.Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TPasRecordType }
|
||||||
|
|
||||||
procedure TPasRecordType.GetMembers(S: TStrings);
|
procedure TPasRecordType.GetMembers(S: TStrings);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
@ -4049,17 +4083,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasRecordType.SetParent(const AValue: TPasElement);
|
|
||||||
begin
|
|
||||||
if (AValue=nil) and (Parent<>nil) then
|
|
||||||
begin
|
|
||||||
// parent is cleared
|
|
||||||
// -> clear all child references to this class (releasing loops)
|
|
||||||
ForEachCall(@ClearChildReferences,nil);
|
|
||||||
end;
|
|
||||||
inherited SetParent(AValue);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TPasRecordType.GetDeclaration (full : boolean) : string;
|
function TPasRecordType.GetDeclaration (full : boolean) : string;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
@ -4093,54 +4116,30 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
inherited ForEachCall(aMethodCall, Arg);
|
inherited ForEachCall(aMethodCall, Arg);
|
||||||
for i:=0 to GenericTemplateTypes.Count-1 do
|
|
||||||
ForEachChildCall(aMethodCall,Arg,TPasElement(GenericTemplateTypes[i]),true);
|
|
||||||
for i:=0 to Members.Count-1 do
|
|
||||||
ForEachChildCall(aMethodCall,Arg,TPasElement(Members[i]),false);
|
|
||||||
ForEachChildCall(aMethodCall,Arg,VariantEl,true);
|
ForEachChildCall(aMethodCall,Arg,VariantEl,true);
|
||||||
if Variants<>nil then
|
if Variants<>nil then
|
||||||
for i:=0 to Variants.Count-1 do
|
for i:=0 to Variants.Count-1 do
|
||||||
ForEachChildCall(aMethodCall,Arg,TPasElement(Variants[i]),false);
|
ForEachChildCall(aMethodCall,Arg,TPasElement(Variants[i]),false);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasRecordType.IsPacked: Boolean;
|
|
||||||
begin
|
|
||||||
Result:=(PackMode <> pmNone);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TPasRecordType.IsBitPacked: Boolean;
|
|
||||||
begin
|
|
||||||
Result:=(PackMode=pmBitPacked)
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TPasRecordType.IsAdvancedRecord: Boolean;
|
function TPasRecordType.IsAdvancedRecord: Boolean;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
I : Integer;
|
I : Integer;
|
||||||
|
Member: TPasElement;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Result:=False;
|
Result:=False;
|
||||||
I:=0;
|
I:=0;
|
||||||
While (Not Result) and (I<Members.Count) do
|
While (Not Result) and (I<Members.Count) do
|
||||||
begin
|
begin
|
||||||
Result:=TPasElement(Members[i]).InheritsFrom(TPasProcedureBase) or
|
Member:=TPasElement(Members[i]);
|
||||||
TPasElement(Members[i]).InheritsFrom(TPasProperty);
|
if (Member.Visibility<>visPublic) then exit(true);
|
||||||
|
if (Member.ClassType<>TPasVariable) then exit(true);
|
||||||
Inc(I);
|
Inc(I);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasRecordType.SetGenericTemplates(AList: TFPList);
|
|
||||||
var
|
|
||||||
I: Integer;
|
|
||||||
begin
|
|
||||||
For I:=0 to AList.Count-1 do
|
|
||||||
begin
|
|
||||||
TPasElement(AList[i]).Parent:=Self;
|
|
||||||
GenericTemplateTypes.Add(AList[i]);
|
|
||||||
end;
|
|
||||||
AList.Clear;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TPasProcedureType.GetArguments(List : TStrings);
|
procedure TPasProcedureType.GetArguments(List : TStrings);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
|
@ -1479,6 +1479,25 @@ begin
|
|||||||
begin
|
begin
|
||||||
BuiltInProc:=TResElDataBuiltInProc(Decl.CustomData);
|
BuiltInProc:=TResElDataBuiltInProc(Decl.CustomData);
|
||||||
case BuiltInProc.BuiltIn of
|
case BuiltInProc.BuiltIn of
|
||||||
|
bfExit:
|
||||||
|
begin
|
||||||
|
if El.Parent is TParamsExpr then
|
||||||
|
begin
|
||||||
|
Params:=(El.Parent as TParamsExpr).Params;
|
||||||
|
if length(Params)=1 then
|
||||||
|
begin
|
||||||
|
SubEl:=El.Parent;
|
||||||
|
while (SubEl<>nil) and not (SubEl is TPasProcedure) do
|
||||||
|
SubEl:=SubEl.Parent;
|
||||||
|
if (SubEl is TPasProcedure)
|
||||||
|
and (TPasProcedure(SubEl).ProcType is TPasFunctionType) then
|
||||||
|
begin
|
||||||
|
SubEl:=TPasFunctionType(TPasProcedure(SubEl).ProcType).ResultEl;
|
||||||
|
UseElement(SubEl,rraAssign,false);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
bfTypeInfo:
|
bfTypeInfo:
|
||||||
begin
|
begin
|
||||||
Params:=(El.Parent as TParamsExpr).Params;
|
Params:=(El.Parent as TParamsExpr).Params;
|
||||||
@ -1490,9 +1509,10 @@ begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
if ParamResolved.IdentEl=nil then
|
if ParamResolved.IdentEl=nil then
|
||||||
RaiseNotSupported(20180628155107,Params[0]);
|
RaiseNotSupported(20180628155107,Params[0]);
|
||||||
if ParamResolved.IdentEl is TPasFunction then
|
if (ParamResolved.IdentEl is TPasProcedure)
|
||||||
|
and (TPasProcedure(ParamResolved.IdentEl).ProcType is TPasFunctionType) then
|
||||||
begin
|
begin
|
||||||
SubEl:=TPasFunction(ParamResolved.IdentEl).FuncType.ResultEl.ResultType;
|
SubEl:=TPasFunctionType(TPasProcedure(ParamResolved.IdentEl).ProcType).ResultEl.ResultType;
|
||||||
MarkImplScopeRef(El,SubEl,psraTypeInfo);
|
MarkImplScopeRef(El,SubEl,psraTypeInfo);
|
||||||
UseTypeInfo(SubEl);
|
UseTypeInfo(SubEl);
|
||||||
end
|
end
|
||||||
|
@ -81,7 +81,7 @@ const
|
|||||||
nErrRecordConstantsNotAllowed = 2035;
|
nErrRecordConstantsNotAllowed = 2035;
|
||||||
nErrRecordMethodsNotAllowed = 2036;
|
nErrRecordMethodsNotAllowed = 2036;
|
||||||
nErrRecordPropertiesNotAllowed = 2037;
|
nErrRecordPropertiesNotAllowed = 2037;
|
||||||
nErrRecordVisibilityNotAllowed = 2038;
|
// free , was nErrRecordVisibilityNotAllowed = 2038;
|
||||||
nParserTypeNotAllowedHere = 2039;
|
nParserTypeNotAllowedHere = 2039;
|
||||||
nParserNotAnOperand = 2040;
|
nParserNotAnOperand = 2040;
|
||||||
nParserArrayPropertiesCannotHaveDefaultValue = 2041;
|
nParserArrayPropertiesCannotHaveDefaultValue = 2041;
|
||||||
@ -142,7 +142,7 @@ resourcestring
|
|||||||
SErrRecordVariablesNotAllowed = 'Record variables not allowed at this location.';
|
SErrRecordVariablesNotAllowed = 'Record variables not allowed at this location.';
|
||||||
SErrRecordMethodsNotAllowed = 'Record methods not allowed at this location.';
|
SErrRecordMethodsNotAllowed = 'Record methods not allowed at this location.';
|
||||||
SErrRecordPropertiesNotAllowed = 'Record properties not allowed at this location.';
|
SErrRecordPropertiesNotAllowed = 'Record properties not allowed at this location.';
|
||||||
SErrRecordVisibilityNotAllowed = 'Record visibilities not allowed at this location.';
|
// free, was SErrRecordVisibilityNotAllowed = 'Record visibilities not allowed at this location.';
|
||||||
SParserTypeNotAllowedHere = 'Type "%s" not allowed here';
|
SParserTypeNotAllowedHere = 'Type "%s" not allowed here';
|
||||||
SParserNotAnOperand = 'Not an operand: (%d : %s)';
|
SParserNotAnOperand = 'Not an operand: (%d : %s)';
|
||||||
SParserArrayPropertiesCannotHaveDefaultValue = 'Array properties cannot have default value';
|
SParserArrayPropertiesCannotHaveDefaultValue = 'Array properties cannot have default value';
|
||||||
@ -4504,7 +4504,7 @@ begin
|
|||||||
ParseVarList(Parent,List,AVisibility,False);
|
ParseVarList(Parent,List,AVisibility,False);
|
||||||
tt:=[tkEnd,tkSemicolon];
|
tt:=[tkEnd,tkSemicolon];
|
||||||
if ClosingBrace then
|
if ClosingBrace then
|
||||||
include(tt,tkBraceClose);
|
Include(tt,tkBraceClose);
|
||||||
if not (CurToken in tt) then
|
if not (CurToken in tt) then
|
||||||
ParseExc(nParserExpectedSemiColonEnd,SParserExpectedSemiColonEnd);
|
ParseExc(nParserExpectedSemiColonEnd,SParserExpectedSemiColonEnd);
|
||||||
end;
|
end;
|
||||||
@ -6362,15 +6362,13 @@ begin
|
|||||||
tkGeneric, // Counts as field name
|
tkGeneric, // Counts as field name
|
||||||
tkIdentifier :
|
tkIdentifier :
|
||||||
begin
|
begin
|
||||||
if CheckVisibility(CurtokenString,v) then
|
If AllowMethods and CheckVisibility(CurTokenString,v) then
|
||||||
begin
|
begin
|
||||||
If not (msAdvancedRecords in Scanner.CurrentModeSwitches) then
|
if not (v in [visPrivate,visPublic,visStrictPrivate]) then
|
||||||
ParseExc(nErrRecordVisibilityNotAllowed,SErrRecordVisibilityNotAllowed);
|
ParseExc(nParserInvalidRecordVisibility,SParserInvalidRecordVisibility);
|
||||||
if not (v in [visPrivate,visPublic,visStrictPrivate]) then
|
NextToken;
|
||||||
ParseExc(nParserInvalidRecordVisibility,SParserInvalidRecordVisibility);
|
Continue;
|
||||||
NextToken;
|
end;
|
||||||
Continue;
|
|
||||||
end;
|
|
||||||
OldCount:=ARec.Members.Count;
|
OldCount:=ARec.Members.Count;
|
||||||
ParseInlineVarDecl(ARec, ARec.Members, v, AEndToken=tkBraceClose);
|
ParseInlineVarDecl(ARec, ARec.Members, v, AEndToken=tkBraceClose);
|
||||||
for i:=OldCount to ARec.Members.Count-1 do
|
for i:=OldCount to ARec.Members.Count-1 do
|
||||||
@ -6423,12 +6421,15 @@ begin
|
|||||||
try
|
try
|
||||||
Result.PackMode:=PackMode;
|
Result.PackMode:=PackMode;
|
||||||
NextToken;
|
NextToken;
|
||||||
ParseRecordFieldList(Result,tkEnd,true);
|
ParseRecordFieldList(Result,tkEnd,msAdvancedRecords in Scanner.CurrentModeSwitches);
|
||||||
Engine.FinishScope(stTypeDef,Result);
|
Engine.FinishScope(stTypeDef,Result);
|
||||||
ok:=true;
|
ok:=true;
|
||||||
finally
|
finally
|
||||||
if not ok then
|
if not ok then
|
||||||
|
begin
|
||||||
|
Result.Parent:=nil; // clear references from members to Result
|
||||||
Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
|
Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -6826,7 +6827,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if ((AobjKind in [okClass,OKInterface]) and (msExternalClass in CurrentModeswitches) and CurTokenIsIdentifier('external')) then
|
if ((AObjKind in [okClass,OKInterface]) and (msExternalClass in CurrentModeswitches)
|
||||||
|
and CurTokenIsIdentifier('external')) then
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
if CurToken<>tkString then
|
if CurToken<>tkString then
|
||||||
|
@ -483,7 +483,27 @@ type
|
|||||||
Procedure TestRecord_Const_UntypedFail;
|
Procedure TestRecord_Const_UntypedFail;
|
||||||
Procedure TestRecord_Const_NestedRecord;
|
Procedure TestRecord_Const_NestedRecord;
|
||||||
Procedure TestRecord_Const_Variant;
|
Procedure TestRecord_Const_Variant;
|
||||||
Procedure TestRecord_VarExternal; // ToDo
|
Procedure TestRecord_VarExternal;
|
||||||
|
Procedure TestRecord_VarSelfFail;
|
||||||
|
|
||||||
|
// advanced record
|
||||||
|
Procedure TestAdvRecord;
|
||||||
|
Procedure TestAdvRecord_Private; // ToDo
|
||||||
|
// Todo: Procedure TestAdvRecord_ForwardFail
|
||||||
|
// ToDo: public, private, strict private
|
||||||
|
// ToDo: TestAdvRecordPublsihedFail
|
||||||
|
// ToDo: TestAdvRecord_VirtualFail
|
||||||
|
// ToDo: TestAdvRecord_OverrideFail
|
||||||
|
// ToDo: constructor, destructor
|
||||||
|
// ToDo: class function/procedure
|
||||||
|
// ToDo: nested record type
|
||||||
|
// ToDo: const
|
||||||
|
// todo: var
|
||||||
|
// todo: class var
|
||||||
|
// todo: property
|
||||||
|
// todo: class property
|
||||||
|
// todo: TestRecordAsFuncResult
|
||||||
|
// todo: for in record
|
||||||
|
|
||||||
// class
|
// class
|
||||||
Procedure TestClass;
|
Procedure TestClass;
|
||||||
@ -1579,7 +1599,7 @@ begin
|
|||||||
if (Msg<>E.Message) and (Msg<>E.MsgPattern) and (Msg<>Full) then
|
if (Msg<>E.Message) and (Msg<>E.MsgPattern) and (Msg<>Full) then
|
||||||
begin
|
begin
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
writeln('TCustomTestResolver.CheckResolverException E.MsgPattern={',E.MsgPattern,'}');
|
writeln('TCustomTestResolver.CheckResolverException E.MsgPattern={',E.MsgPattern,'} E.Message={',E.Message,'} Full={',Full,'}');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
AssertEquals('Expected message ('+IntToStr(MsgNumber)+')',
|
AssertEquals('Expected message ('+IntToStr(MsgNumber)+')',
|
||||||
'{'+Msg+'}','{'+E.Message+'} OR {'+E.MsgPattern+'} OR {'+Full+'}');
|
'{'+Msg+'}','{'+E.Message+'} OR {'+E.MsgPattern+'} OR {'+Full+'}');
|
||||||
@ -7787,6 +7807,55 @@ begin
|
|||||||
ParseProgram;
|
ParseProgram;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestRecord_VarSelfFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TRec = record',
|
||||||
|
' r: Trec;',
|
||||||
|
' end;',
|
||||||
|
'begin']);
|
||||||
|
CheckResolverException('type "TRec" is not yet completely defined',nTypeXIsNotYetCompletelyDefined);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAdvRecord;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'{$modeswitch advancedrecords}',
|
||||||
|
'type',
|
||||||
|
' TRec = record',
|
||||||
|
' procedure DoIt;',
|
||||||
|
' end;',
|
||||||
|
'procedure TRec.DoIt;',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'begin']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAdvRecord_Private;
|
||||||
|
begin
|
||||||
|
exit;
|
||||||
|
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'{$modeswitch advancedrecords}',
|
||||||
|
'type',
|
||||||
|
' TRec = record',
|
||||||
|
' private',
|
||||||
|
' a: byte;',
|
||||||
|
' public',
|
||||||
|
' b: byte;',
|
||||||
|
' end;',
|
||||||
|
'var',
|
||||||
|
' r: TRec;',
|
||||||
|
'begin',
|
||||||
|
' r.a:=r.b;']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestResolver.TestClass;
|
procedure TTestResolver.TestClass;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
@ -2043,6 +2043,7 @@ Var
|
|||||||
P : TPasFunction;
|
P : TPasFunction;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
Scanner.CurrentModeSwitches:=Scanner.CurrentModeSwitches+[msAdvancedRecords];
|
||||||
TestFields(['x : integer;','class operator assign(a : ta; b : Cardinal) : boolean;','function dosomething3 : Integer;'],'',False);
|
TestFields(['x : integer;','class operator assign(a : ta; b : Cardinal) : boolean;','function dosomething3 : Integer;'],'',False);
|
||||||
AssertEquals('Member count',3,TheRecord.Members.Count);
|
AssertEquals('Member count',3,TheRecord.Members.Count);
|
||||||
AssertField1([]);
|
AssertField1([]);
|
||||||
@ -2057,6 +2058,7 @@ end;
|
|||||||
|
|
||||||
procedure TTestRecordTypeParser.TestFieldAndClassVar;
|
procedure TTestRecordTypeParser.TestFieldAndClassVar;
|
||||||
begin
|
begin
|
||||||
|
Scanner.CurrentModeSwitches:=Scanner.CurrentModeSwitches+[msAdvancedRecords];
|
||||||
TestFields(['x : integer;','class var y : integer;'],'',False);
|
TestFields(['x : integer;','class var y : integer;'],'',False);
|
||||||
AssertField1([]);
|
AssertField1([]);
|
||||||
AssertTrue('Second field is class var',vmClass in Field2.VarModifiers);
|
AssertTrue('Second field is class var',vmClass in Field2.VarModifiers);
|
||||||
@ -2064,6 +2066,7 @@ end;
|
|||||||
|
|
||||||
procedure TTestRecordTypeParser.TestFieldAndVar;
|
procedure TTestRecordTypeParser.TestFieldAndVar;
|
||||||
begin
|
begin
|
||||||
|
Scanner.CurrentModeSwitches:=Scanner.CurrentModeSwitches+[msAdvancedRecords];
|
||||||
TestFields(['x : integer;','var y : integer;'],'',False);
|
TestFields(['x : integer;','var y : integer;'],'',False);
|
||||||
AssertField1([]);
|
AssertField1([]);
|
||||||
AssertTrue('Second field is regular var',not (vmClass in Field2.VarModifiers));
|
AssertTrue('Second field is regular var',not (vmClass in Field2.VarModifiers));
|
||||||
|
@ -128,6 +128,7 @@ type
|
|||||||
procedure TestM_Hint_FunctionResultRecord;
|
procedure TestM_Hint_FunctionResultRecord;
|
||||||
procedure TestM_Hint_FunctionResultPassRecordElement;
|
procedure TestM_Hint_FunctionResultPassRecordElement;
|
||||||
procedure TestM_Hint_FunctionResultAssembler;
|
procedure TestM_Hint_FunctionResultAssembler;
|
||||||
|
procedure TestM_Hint_FunctionResultExit;
|
||||||
procedure TestM_Hint_AbsoluteVar;
|
procedure TestM_Hint_AbsoluteVar;
|
||||||
|
|
||||||
// whole program optimization
|
// whole program optimization
|
||||||
@ -2158,6 +2159,20 @@ begin
|
|||||||
CheckUseAnalyzerUnexpectedHints;
|
CheckUseAnalyzerUnexpectedHints;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestUseAnalyzer.TestM_Hint_FunctionResultExit;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'function GetIt: longint;',
|
||||||
|
'begin',
|
||||||
|
' exit(3);',
|
||||||
|
'end;',
|
||||||
|
'begin',
|
||||||
|
' GetIt;']);
|
||||||
|
AnalyzeProgram;
|
||||||
|
CheckUseAnalyzerUnexpectedHints;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestUseAnalyzer.TestM_Hint_AbsoluteVar;
|
procedure TTestUseAnalyzer.TestM_Hint_AbsoluteVar;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user