fcl-passrc: added modeswitch ignoreinterfaces, typecast enum to integer

git-svn-id: trunk@37335 -
This commit is contained in:
Mattias Gaertner 2017-09-27 20:04:14 +00:00
parent a52b675779
commit b69ffccb44
5 changed files with 177 additions and 10 deletions

View File

@ -1387,6 +1387,7 @@ type
function GetSmallestIntegerBaseType(MinVal, MaxVal: MaxPrecInt): TResolverBaseType;
function GetCombinedChar(const Char1, Char2: TPasResolverResult; ErrorEl: TPasElement): TResolverBaseType; virtual;
function GetCombinedString(const Str1, Str2: TPasResolverResult; ErrorEl: TPasElement): TResolverBaseType; virtual;
function IsElementSkipped(El: TPasElement): boolean; virtual;
public
// options
property Options: TPasResolverOptions read FOptions write FOptions;
@ -3457,7 +3458,10 @@ procedure TPasResolver.FinishConstDef(El: TPasConst);
begin
ResolveExpr(El.Expr,rraRead);
if El.VarType<>nil then
CheckAssignCompatibility(El,El.Expr,true)
begin
CheckAssignCompatibility(El,El.Expr,true);
EmitTypeHints(El,El.VarType);
end
else
Eval(El.Expr,[refConst])
end;
@ -3610,6 +3614,9 @@ begin
if not IsValidIdent(ProcName) then
RaiseNotYetImplemented(20160922163407,El);
if El is TPasFunctionType then
EmitTypeHints(TPasFunctionType(El).ResultEl,TPasFunctionType(El).ResultEl.ResultType);
if Proc.LibraryExpr<>nil then
ResolveExpr(Proc.LibraryExpr,rraRead);
if Proc.LibrarySymbolName<>nil then
@ -4405,7 +4412,12 @@ begin
if aClass.IsForward then
exit;
if aClass.ObjKind<>okClass then
begin
if (aClass.ObjKind=okInterface)
and (msIgnoreInterfaces in CurrentParser.CurrentModeswitches) then
exit;
RaiseNotYetImplemented(20161010174638,aClass,'Kind='+ObjKindNames[aClass.ObjKind]);
end;
IsSealed:=false;
for i:=0 to aClass.Modifiers.Count-1 do
@ -4443,7 +4455,10 @@ begin
else
begin
AncestorEl:=TPasClassType(AncestorType);
EmitTypeHints(aClass,AncestorEl);
if AncestorEl.ObjKind<>okClass then
AncestorEl:=nil
else
EmitTypeHints(aClass,AncestorEl);
end;
AncestorClassScope:=nil;
@ -4502,6 +4517,8 @@ begin
CanonicalSelf.Visibility:=visStrictPrivate;
CanonicalSelf.SourceFilename:=aClass.SourceFilename;
CanonicalSelf.SourceLinenumber:=aClass.SourceLinenumber;
// ToDo: interfaces
end;
procedure TPasResolver.FinishPropertyParamAccess(Params: TParamsExpr;
@ -4542,6 +4559,8 @@ end;
function TPasResolver.EmitElementHints(PosEl, El: TPasElement): boolean;
begin
if IsElementSkipped(El) then
RaiseMsg(20170927160030,nNotYetImplemented,sNotYetImplemented,[GetObjName(El)],PosEl);
if El.Hints=[] then exit(false);
Result:=true;
if hDeprecated in El.Hints then
@ -5923,6 +5942,7 @@ var
Proc: TPasProcedure;
aClassType: TPasClassType;
begin
if IsElementSkipped(El) then exit;
if El is TPasDeclarations then
begin
for i:=0 to TPasDeclarations(El).Declarations.Count-1 do
@ -9262,6 +9282,8 @@ begin
if FRootElement=nil then
FRootElement:=Result as TPasModule;
if IsElementSkipped(El) then exit;
// create scope
if (AClass=TPasVariable)
or (AClass=TPasConst) then
@ -9797,6 +9819,7 @@ end;
procedure TPasResolver.FinishScope(ScopeType: TPasScopeType; El: TPasElement);
begin
if IsElementSkipped(El) then exit;
case ScopeType of
stModule: FinishModule(El as TPasModule);
stUsesClause: FinishUsesClause;
@ -11654,11 +11677,15 @@ end;
function TPasResolver.ResolvedElIsClassInstance(
const ResolvedEl: TPasResolverResult): boolean;
var
TypeEl: TPasType;
begin
Result:=false;
if ResolvedEl.BaseType<>btContext then exit;
if ResolvedEl.TypeEl=nil then exit;
if ResolvedEl.TypeEl.ClassType<>TPasClassType then exit;
TypeEl:=ResolvedEl.TypeEl;
if TypeEl=nil then exit;
if TypeEl.ClassType<>TPasClassType then exit;
if TPasClassType(TypeEl).ObjKind<>okClass then exit;
if (ResolvedEl.IdentEl is TPasVariable)
or (ResolvedEl.IdentEl.ClassType=TPasArgument)
or (ResolvedEl.IdentEl.ClassType=TPasResultElement) then
@ -12571,7 +12598,13 @@ begin
if FromResolved.BaseType in btAllInteger then
Result:=cCompatible
else if FromResolved.BaseType in btAllBooleans then
Result:=cCompatible;
Result:=cCompatible
else if FromResolved.BaseType=btContext then
begin
if FromResolved.TypeEl.ClassType=TPasEnumType then
// e.g. longint(TEnum)
Result:=cCompatible;
end;
end
else if ToTypeBaseType in btAllFloats then
begin
@ -13987,6 +14020,25 @@ begin
Result:=btString;
end;
function TPasResolver.IsElementSkipped(El: TPasElement): boolean;
var
C: TClass;
aClass: TPasClassType;
begin
while El<>nil do
begin
C:=El.ClassType;
if C.ClassType=TPasClassType then
begin
aClass:=TPasClassType(El);
if aClass.ObjKind=okInterface then
exit(true);
end;
El:=El.Parent;
end;
Result:=false;
end;
function TPasResolver.CheckSrcIsADstType(const ResolvedSrcType,
ResolvedDestType: TPasResolverResult; ErrorEl: TPasElement): integer;
// finds distance between classes SrcType and DestType

View File

@ -1287,6 +1287,9 @@ var
ClassScope: TPasClassScope;
Ref: TResolvedReference;
begin
if El.ObjKind=okInterface then
exit;
FirstTime:=true;
case Mode of
paumAllExports: exit;

View File

@ -262,7 +262,8 @@ type
msISOLikeIO, { I/O as it required by an ISO compatible compiler }
msISOLikeProgramsPara, { program parameters as it required by an ISO compatible compiler }
msISOLikeMod, { mod operation as it is required by an iso compatible compiler }
msExternalClass { Allow external class definitions }
msExternalClass, { Allow external class definitions }
msIgnoreInterfaces { workaround til resolver/converter supports interfaces }
);
TModeSwitches = Set of TModeSwitch;
@ -815,7 +816,8 @@ const
'ISOIO',
'ISOPROGRAMPARAS',
'ISOMOD',
'EXTERNALCLASS'
'EXTERNALCLASS',
'IGNOREINTERFACES'
);
LetterSwitchNames: array['A'..'Z'] of string=(

View File

@ -520,6 +520,12 @@ type
Procedure TestDefaultProperty;
Procedure TestMissingDefaultProperty;
// class interfaces
Procedure TestIgnoreInterfaces;
Procedure TestInterfaceVarFail;
Procedure TestInterfaceArgFail;
Procedure TestInterfaceFunctionResultFail;
// with
Procedure TestWithBlock1;
Procedure TestWithBlock2;
@ -738,9 +744,9 @@ begin
aRow:=E.Row;
aCol:=E.Column;
WriteSources(aFilename,aRow,aCol);
writeln('ERROR: TTestResolver.ParseProgram Parser: '+E.ClassName+':'+E.Message
+' Scanner at'
+' at '+aFilename+'('+IntToStr(aRow)+','+IntToStr(aCol)+')'
writeln('ERROR: TTestResolver.ParseProgram Parser: '+E.ClassName+':'+E.Message,
' Scanner at'
+' '+aFilename+'('+IntToStr(aRow)+','+IntToStr(aCol)+')'
+' Line="'+Scanner.CurLine+'"');
Fail(E.Message);
end;
@ -2636,6 +2642,7 @@ begin
Add('var');
Add(' {#f}{=TFlag}f: TFlag;');
Add(' {#v}{=TFlag}v: TFlag = Green;');
Add(' {#i}i: longint;');
Add('begin');
Add(' {@f}f:={@Red}Red;');
Add(' {@f}f:={@v}v;');
@ -2648,6 +2655,8 @@ begin
Add(' if {@f}f<>{@v}v then ;');
Add(' if ord({@f}f)<>ord({@Red}Red) then ;');
Add(' {@f}f:={@TFlag}TFlag.{@Red}Red;');
Add(' {@f}f:={@TFlag}TFlag({@i}i);');
Add(' {@i}i:=longint({@f}f);');
ParseProgram;
end;
@ -8336,6 +8345,77 @@ begin
nIllegalQualifier);
end;
procedure TTestResolver.TestIgnoreInterfaces;
begin
StartProgram(false);
Add([
'{$modeswitch ignoreinterfaces}',
'type',
' TGUID = record end;',
' IUnknown = interface;',
' IUnknown = interface',
' [''{00000000-0000-0000-C000-000000000046}'']',
' function QueryInterface(const iid : tguid;out obj) : longint;',
' function _AddRef : longint; cdecl;',
' function _Release : longint; stdcall;',
' end;',
' IInterface = IUnknown;',
' TObject = class',
' ClassName: string;',
' end;',
' TInterfacedObject = class(TObject,IUnknown)',
' RefCount : longint;',
' end;',
'var i: TInterfacedObject;',
'begin',
' i.ClassName:=''a'';',
' i.RefCount:=3;',
'']);
ParseProgram;
end;
procedure TTestResolver.TestInterfaceVarFail;
begin
StartProgram(false);
Add([
'{$modeswitch ignoreinterfaces}',
'type',
' IUnknown = interface',
' end;',
'var i: IUnknown;',
'begin',
'']);
CheckResolverException('not yet implemented: IUnknown:TPasClassType',nNotYetImplemented);
end;
procedure TTestResolver.TestInterfaceArgFail;
begin
StartProgram(false);
Add([
'{$modeswitch ignoreinterfaces}',
'type',
' IUnknown = interface',
' end;',
'procedure DoIt(i: IUnknown); begin end;',
'begin',
'']);
CheckResolverException('not yet implemented: IUnknown:TPasClassType',nNotYetImplemented);
end;
procedure TTestResolver.TestInterfaceFunctionResultFail;
begin
StartProgram(false);
Add([
'{$modeswitch ignoreinterfaces}',
'type',
' IUnknown = interface',
' end;',
'function DoIt: IUnknown; begin end;',
'begin',
'']);
CheckResolverException('not yet implemented: IUnknown:TPasClassType',nNotYetImplemented);
end;
procedure TTestResolver.TestPropertyAssign;
begin
StartProgram(false);

View File

@ -72,6 +72,7 @@ type
procedure TestM_Class_PropertyOverride;
procedure TestM_Class_MethodOverride;
procedure TestM_Class_MethodOverride2;
procedure TestM_ClassInterface_Ignore;
procedure TestM_TryExceptStatement;
// single module hints
@ -828,6 +829,35 @@ begin
AnalyzeProgram;
end;
procedure TTestUseAnalyzer.TestM_ClassInterface_Ignore;
begin
StartProgram(false);
Add([
'{$modeswitch ignoreinterfaces}',
'type',
' TGUID = record end;',
' IUnknown = interface;',
' IUnknown = interface',
' [''{00000000-0000-0000-C000-000000000046}'']',
' function QueryInterface(const iid : tguid;out obj) : longint;',
' function _AddRef : longint; cdecl;',
' function _Release : longint; stdcall;',
' end;',
' IInterface = IUnknown;',
' TObject = class',
' ClassName: string;',
' end;',
' TInterfacedObject = class(TObject,IUnknown)',
' RefCount : longint;',
' end;',
'var i: TInterfacedObject;',
'begin',
' i.ClassName:=''a'';',
' i.RefCount:=3;',
'']);
AnalyzeProgram;
end;
procedure TTestUseAnalyzer.TestM_TryExceptStatement;
begin
StartProgram(false);