fcl-passrc: resolver: implemented $M $TypeInfo

git-svn-id: trunk@37468 -
This commit is contained in:
Mattias Gaertner 2017-10-16 10:16:13 +00:00
parent 34c88e6dbc
commit 2ac2e7bd7d
4 changed files with 120 additions and 40 deletions

View File

@ -76,6 +76,7 @@ Works:
- visibility, override: warn and fix if lower
- events, proc type of object
- sealed
- $M+ / $TYPEINFO use visPublished as default visibility
- with..do
- enums - TPasEnumType, TPasEnumValue
- propagate to parent scopes
@ -587,7 +588,8 @@ type
TPasClassScopeFlag = (
pcsfAncestorResolved,
pcsfSealed
pcsfSealed,
pcsfPublished // default visibility is published due to $M directive
);
TPasClassScopeFlags = set of TPasClassScopeFlag;
@ -1229,6 +1231,8 @@ type
function GetVisibilityContext: TPasElement;
procedure FinishScope(ScopeType: TPasScopeType; El: TPasElement); override;
function NeedArrayValues(El: TPasElement): boolean; override;
function GetDefaultClassVisibility(AClass: TPasClassType
): TPasMemberVisibility; override;
// built in types and functions
procedure ClearBuiltInIdentifiers; virtual;
procedure AddObjFPCBuiltInIdentifiers(
@ -4618,7 +4622,11 @@ begin
begin
ClassScope.AncestorScope:=NoNil(AncestorEl.CustomData) as TPasClassScope;
ClassScope.DefaultProperty:=ClassScope.AncestorScope.DefaultProperty;
if pcsfPublished in ClassScope.AncestorScope.Flags then
Include(ClassScope.Flags,pcsfPublished);
end;
if CurrentParser.Scanner.IsDefined(LetterSwitchNames['M']) then
Include(ClassScope.Flags,pcsfPublished);
// create canonical class-of for the "Self" in class functions
CanonicalSelf:=TPasClassOfType.Create('Self',aClass);
ClassScope.CanonicalClassOf:=CanonicalSelf;
@ -10069,6 +10077,20 @@ begin
//writeln('TPasResolver.NeedArrayValues ',GetObjName(El));
end;
function TPasResolver.GetDefaultClassVisibility(AClass: TPasClassType
): TPasMemberVisibility;
var
ClassScope: TPasClassScope;
begin
if AClass.CustomData=nil then
exit(visDefault);
ClassScope:=(AClass.CustomData as TPasClassScope);
if pcsfPublished in ClassScope.Flags then
Result:=visPublished
else
Result:=visPublic;
end;
class procedure TPasResolver.UnmangleSourceLineNumber(LineNumber: integer; out
Line, Column: integer);
begin

View File

@ -773,7 +773,7 @@ end;
function TPasTreeContainer.GetDefaultClassVisibility(AClass: TPasClassType
): TPasMemberVisibility;
begin
Result:=visPublic;
Result:=visDefault;
if AClass=nil then ;
end;

View File

@ -45,7 +45,7 @@ type
procedure TearDown; override;
procedure DefaultMethod;
Procedure AssertParserError(Const Msg : String);
Procedure AssertVisibility(V : TPasMemberVisibility = visPublic; Member : TPasElement = Nil);
Procedure AssertVisibility(V : TPasMemberVisibility = visDefault; Member : TPasElement = Nil);
procedure AssertMemberType(AType : TClass; Member : TPaselement = Nil);
procedure AssertMemberName(AName : string; Member : TPaselement = Nil);
Procedure AssertProperty(P : TPasProperty; AVisibility : TPasMemberVisibility;AName,ARead,AWrite,AStored,AImplements : String; AArgCount : Integer; ADefault,ANodefault : Boolean);
@ -680,7 +680,7 @@ begin
AssertNotNull('Have field',Members[1]);
AssertMemberName('b',Members[1]);
AssertMemberType(TPasVariable,Members[1]);
AssertVisibility(visPublic,Members[1]);
AssertVisibility(visDefault,Members[1]);
end;
procedure TTestClassType.TestTwoFieldsB;
@ -694,7 +694,7 @@ begin
AssertNotNull('Have field',Members[1]);
AssertMemberName('b',Members[1]);
AssertMemberType(TPasVariable,Members[1]);
AssertVisibility(visPublic,Members[1]);
AssertVisibility(visDefault,Members[1]);
end;
procedure TTestClassType.TestTwoVarFieldsB;
@ -879,7 +879,7 @@ begin
AddMember('Procedure DoSomething');
ParseClass;
AssertEquals('1 members',1,TheClass.members.Count);
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertNotNull('Have method',Method1);
AssertMemberName('DoSomething');
AssertEquals('No modifiers',[],Method1.Modifiers);
@ -894,7 +894,7 @@ begin
AddMember('{c} Procedure DoSomething');
ParseClass;
AssertEquals('1 members',1,TheClass.members.Count);
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertNotNull('Have method',Method1);
AssertMemberName('DoSomething');
AssertEquals('Comment','c'+sLineBreak,Method1.DocComment);
@ -912,7 +912,7 @@ begin
ParseClass;
AssertEquals('1 members',1,TheClass.members.Count);
AssertEquals('1 class procedure',TPasClassProcedure,members[0].ClassType);
AssertEquals('Public visibility',visPublic,Members[0].Visibility);
AssertEquals('Default visibility',visDefault,Members[0].Visibility);
AssertMemberName('DoSomething');
AssertEquals('No modifiers',[],TPasClassProcedure(Members[0]).Modifiers);
AssertEquals('Default calling convention',ccDefault, TPasClassProcedure(Members[0]).ProcType.CallingConvention);
@ -934,7 +934,7 @@ begin
ParseClass;
AssertEquals('1 members',1,TheClass.Members.Count);
AssertEquals('1 class procedure',TPasConstructor,Members[0].ClassType);
AssertEquals('Public visibility',visPublic,Members[0].Visibility);
AssertEquals('Default visibility',visDefault,Members[0].Visibility);
AssertMemberName('Create');
AssertEquals('No modifiers',[],TPasConstructor(Members[0]).Modifiers);
AssertEquals('Default calling convention',ccDefault, TPasConstructor(Members[0]).ProcType.CallingConvention);
@ -948,7 +948,7 @@ begin
ParseClass;
AssertEquals('1 members',1,TheClass.Members.Count);
AssertEquals('1 class procedure',TPasClassConstructor,Members[0].ClassType);
AssertEquals('Public visibility',visPublic,Members[0].Visibility);
AssertEquals('Default visibility',visDefault,Members[0].Visibility);
AssertMemberName('Create');
AssertEquals('No modifiers',[],TPasClassConstructor(Members[0]).Modifiers);
AssertEquals('Default calling convention',ccDefault, TPasClassConstructor(Members[0]).ProcType.CallingConvention);
@ -962,7 +962,7 @@ begin
ParseClass;
AssertEquals('1 members',1,TheClass.members.Count);
AssertEquals('1 class procedure',TPasDestructor,members[0].ClassType);
AssertEquals('Public visibility',visPublic,Members[0].Visibility);
AssertEquals('Default visibility',visDefault,Members[0].Visibility);
AssertMemberName('Destroy');
AssertEquals('No modifiers',[],TPasDestructor(Members[0]).Modifiers);
AssertEquals('Default calling convention',ccDefault, TPasDestructor(Members[0]).ProcType.CallingConvention);
@ -976,7 +976,7 @@ begin
ParseClass;
AssertEquals('1 members',1,TheClass.Members.Count);
AssertEquals('1 class procedure',TPasClassDestructor,Members[0].ClassType);
AssertEquals('Public visibility',visPublic,Members[0].Visibility);
AssertEquals('Default visibility',visDefault,Members[0].Visibility);
AssertMemberName('Destroy');
AssertEquals('No modifiers',[],TPasClassDestructor(Members[0]).Modifiers);
AssertEquals('Default calling convention',ccDefault, TPasClassDestructor(Members[0]).ProcType.CallingConvention);
@ -989,7 +989,7 @@ begin
AddMember('Function DoSomething : integer');
ParseClass;
AssertEquals('1 members',1,TheClass.members.Count);
AssertEquals('Public visibility',visPublic,FunctionMethod1.Visibility);
AssertEquals('Default visibility',visDefault,FunctionMethod1.Visibility);
AssertNotNull('Have method',Member1);
AssertMemberName('DoSomething');
AssertEquals('No modifiers',[],functionMethod1.Modifiers);
@ -1004,7 +1004,7 @@ begin
ParseClass;
AssertEquals('1 members',1,TheClass.members.Count);
AssertEquals('1 class procedure',TPasClassFunction,members[0].ClassType);
AssertEquals('Public visibility',visPublic,Members[0].Visibility);
AssertEquals('Default visibility',visDefault,Members[0].Visibility);
AssertMemberName('DoSomething');
AssertEquals('No modifiers',[],TPasClassFunction(members[0]).Modifiers);
AssertEquals('Default calling convention',ccDefault, TPasClassFunction(members[0]).ProcType.CallingConvention);
@ -1034,7 +1034,7 @@ begin
AddMember('Procedure DoSomething(A : Integer)');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('No modifiers',[],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1044,7 +1044,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) virtual');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Virtual modifiers',[pmVirtual],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1054,7 +1054,7 @@ begin
AddMember('Procedure DoSomething(A : Integer); virtual');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Virtual modifiers',[pmVirtual],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1064,7 +1064,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) virtual abstract');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Virtual, abstract modifiers',[pmVirtual,pmAbstract],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1074,7 +1074,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) virtual; abstract; final');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Virtual, abstract modifiers',[pmVirtual,pmAbstract,pmFinal],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1085,7 +1085,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) override');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Override modifiers',[pmoverride],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1095,7 +1095,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) ReIntroduce');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Reintroduce modifiers',[pmReintroduce],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1105,7 +1105,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) dynamic');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Dynamic modifiers',[pmDynamic],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1115,7 +1115,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) inline');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Inline modifiers',[pmInline],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1138,7 +1138,7 @@ begin
AddMember('Procedure DoSomethingB(A : Integer)');
ParseClass;
DefaultMethod;
AssertEquals('First Default visibility',visPublic,Method1.Visibility);
AssertEquals('First Default visibility',visDefault,Method1.Visibility);
AssertEquals('No modifiers',[],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
AssertNotNull('Have method 2',Method2);
@ -1157,7 +1157,7 @@ begin
ParseClass;
AssertNotNull('Have member 1',Member1);
AssertEquals('Overload',TPasOverloadedProc,Member1.ClassType);
AssertEquals('Public visibility',visPublic,Member1.Visibility);
AssertEquals('Default visibility',visDefault,Member1.Visibility);
end;
procedure TTestClassType.TestMethodHint;
@ -1167,7 +1167,7 @@ begin
DefaultMethod;
HaveHint(hDeprecated,Member1.Hints);
HaveHint(hDeprecated,Method1.ProcType.Hints);
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('No modifiers',[],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1179,7 +1179,7 @@ begin
DefaultMethod;
HaveHint(hDeprecated,Member1.Hints);
HaveHint(hDeprecated,Method1.ProcType.Hints);
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('virtual modifiers',[pmVirtual],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1189,7 +1189,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) message 123');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('message modifier',[pmMessage],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
AssertEquals('Message name','123',Method1.MessageName);
@ -1200,7 +1200,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) message ''aha''');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('message modifiers',[pmMessage],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
AssertEquals('Message name','''aha''',Method1.MessageName);
@ -1212,11 +1212,11 @@ begin
AddMember('Procedure DoSomethingElse');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Virtual modifiers',[pmVirtual],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
AssertEquals('Public visibility',visPublic,Members[1].Visibility);
AssertEquals('Public visibility',TPasProcedure,Members[1].ClassType);
AssertEquals('Default visibility',visDefault,Members[1].Visibility);
AssertEquals('Default visibility',TPasProcedure,Members[1].ClassType);
AssertEquals('Virtual modifiers',[],TPasProcedure(Members[1]).Modifiers);
AssertEquals('Default calling convention',ccDefault, TPasProcedure(Members[1]).ProcType.CallingConvention);
end;
@ -1228,7 +1228,7 @@ begin
AddMember('Procedure DoSomethingElse');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('Virtual modifiers',[pmVirtual],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
AssertEquals('2 Public visibility',visPublic,Members[1].Visibility);
@ -1798,7 +1798,7 @@ begin
AssertEquals('Have helper original alias',TPasUnresolvedTypeRef,TheClass.HelperForType.CLassType);
AssertEquals('Helper original alias name','TOriginal',TheClass.HelperForType.Name);
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('No modifiers',[],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;
@ -1842,7 +1842,7 @@ begin
ParseClass;
AssertEquals('Is interface',okInterface,TheClass.ObjKind);
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('No modifiers',[],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
AssertNull('No UUID',TheClass.GUIDExpr);
@ -1855,7 +1855,7 @@ begin
AddMember('Procedure DoSomething(A : Integer) dispid 12');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('dispid modifier',[pmDispID],Method1.Modifiers);
AssertNotNull('dispid expression',Method1.DispIDExpr);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
@ -1867,7 +1867,7 @@ begin
AddMember('Procedure DoSomething(A : Integer); dispid 12');
ParseClass;
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('dispid modifier',[pmDispID],Method1.Modifiers);
AssertNotNull('dispid expression',Method1.DispIDExpr);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
@ -1887,7 +1887,7 @@ begin
AssertNotNull('Method proc type',FunctionMethod1.ProcType);
AssertMemberName('GetS');
AssertEquals('0 arguments',0,FunctionMethod1.ProcType.Args.Count) ;
AssertEquals('Public visibility',visPublic,FunctionMethod1.Visibility);
AssertEquals('Default visibility',visDefault,FunctionMethod1.Visibility);
AssertEquals('No modifiers',[],FunctionMethod1.Modifiers);
AssertEquals('Default calling convention',ccDefault, FunctionMethod1.ProcType.CallingConvention);
AssertNull('No UUID',TheClass.GUIDExpr);
@ -1977,7 +1977,7 @@ begin
ParseClass;
AssertEquals('Is interface',okInterface,TheClass.ObjKind);
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('No modifiers',[],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
AssertExpression('UUID',TheClass.GUIDExpr,pekString,'''123''');
@ -2015,7 +2015,7 @@ begin
AssertEquals('Have helper original alias',TPasUnresolvedTypeRef,TheClass.HelperForType.ClassType);
AssertEquals('Helper original alias name','TOriginal',TheClass.HelperForType.Name);
DefaultMethod;
AssertEquals('Public visibility',visPublic,Method1.Visibility);
AssertEquals('Default visibility',visDefault,Method1.Visibility);
AssertEquals('No modifiers',[],Method1.Modifiers);
AssertEquals('Default calling convention',ccDefault, Method1.ProcType.CallingConvention);
end;

View File

@ -378,6 +378,7 @@ type
Procedure TestClassDefaultInheritance;
Procedure TestClassTripleInheritance;
Procedure TestClassInheritanceCycleFail;
Procedure TestClassDefaultVisibility;
Procedure TestClassForward;
Procedure TestClassForwardAsAncestorFail;
Procedure TestClassForwardNotResolved;
@ -5551,6 +5552,63 @@ begin
CheckResolverException('Ancestor cycle detected',nAncestorCycleDetected);
end;
procedure TTestResolver.TestClassDefaultVisibility;
var
Elements: TFPList;
El: TPasElement;
aMarker: PSrcMarker;
i: Integer;
begin
StartProgram(false);
Add([
'type',
' TObject = class',
' {#B}b: longint;',
' end;',
' {$M+}',
' TPersistent = class',
' {#C}c: longint;',
' end;',
' {$M-}',
//' TPic = class',
//' {#D}d: longint;',
//' end;',
//' TComponent = class(TPersistent)',
//' {#E}e: longint;',
//' end;',
//' TControl = class(TComponent)',
//' {#F}f: longint;',
//' end;',
'begin']);
ParseProgram;
aMarker:=FirstSrcMarker;
while aMarker<>nil do
begin
//writeln('TTestResolver.TestClassDefaultVisibility',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
Elements:=FindElementsAt(aMarker);
try
for i:=0 to Elements.Count-1 do
begin
El:=TPasElement(Elements[i]);
//writeln('TTestResolver.TestClassDefaultVisibility ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
if not (El is TPasVariable) then continue;
case aMarker^.Identifier of
'B','D':
if El.Visibility<>visPublic then
RaiseErrorAtSrcMarker('expected visPublic at #'+aMarker^.Identifier+', but got '+VisibilityNames[El.Visibility],aMarker);
else
if El.Visibility<>visPublished then
RaiseErrorAtSrcMarker('expected visPublished at #'+aMarker^.Identifier+', but got '+VisibilityNames[El.Visibility],aMarker);
end;
break;
end;
finally
Elements.Free;
end;
aMarker:=aMarker^.Next;
end;
end;
procedure TTestResolver.TestClassForward;
begin
StartProgram(false);