Browse Source

fcl-passrc: resolver: nicer error messages when operator does not fit types

git-svn-id: trunk@38108 -
Mattias Gaertner 7 years ago
parent
commit
4b3d6a7630

+ 4 - 1
packages/fcl-passrc/src/pasresolveeval.pas

@@ -152,6 +152,7 @@ const
   nContextXInvalidY = 3079;
   nContextXInvalidY = 3079;
   nConstructingClassXWithAbstractMethodY = 3080;
   nConstructingClassXWithAbstractMethodY = 3080;
   nXIsNotSupported = 3081;
   nXIsNotSupported = 3081;
+  nOperatorIsNotOverloadedAOpB = 3082;
 
 
 // resourcestring patterns of messages
 // resourcestring patterns of messages
 resourcestring
 resourcestring
@@ -191,7 +192,7 @@ resourcestring
   sWrongNumberOfParametersForTypeCast = 'wrong number of parameters for type cast to %s';
   sWrongNumberOfParametersForTypeCast = 'wrong number of parameters for type cast to %s';
   sIllegalTypeConversionTo = 'Illegal type conversion: "%s" to "%s"';
   sIllegalTypeConversionTo = 'Illegal type conversion: "%s" to "%s"';
   sConstantExpressionExpected = 'Constant expression expected';
   sConstantExpressionExpected = 'Constant expression expected';
-  sLeftSideOfIsOperatorExpectsAClassButGot = 'left side of is-operator expects a class, but got %s';
+  sLeftSideOfIsOperatorExpectsAClassButGot = 'left side of is-operator expects a class, but got "%s"';
   sNotReadable = 'not readable';
   sNotReadable = 'not readable';
   sClassPropertyAccessorMustBeStatic = 'class property accessor must be static';
   sClassPropertyAccessorMustBeStatic = 'class property accessor must be static';
   sClassPropertyAccessorMustNotBeStatic = 'class property accessor must not be static';
   sClassPropertyAccessorMustNotBeStatic = 'class property accessor must not be static';
@@ -236,6 +237,8 @@ resourcestring
   sContextXInvalidY = '%s: invalid %s';
   sContextXInvalidY = '%s: invalid %s';
   sConstructingClassXWithAbstractMethodY = 'Constructing a class "%s" with abstract method "%s"';
   sConstructingClassXWithAbstractMethodY = 'Constructing a class "%s" with abstract method "%s"';
   sXIsNotSupported = '%s is not supported';
   sXIsNotSupported = '%s is not supported';
+  sOperatorIsNotOverloadedAOpB = 'Operator is not overloaded: "%s" %s "%s"';
+
 
 
 type
 type
   { TResolveData - base class for data stored in TPasElement.CustomData }
   { TResolveData - base class for data stored in TPasElement.CustomData }

+ 207 - 111
packages/fcl-passrc/src/pasresolver.pp

@@ -1393,6 +1393,8 @@ type
       Const Fmt : String; Args : Array of const; PosEl: TPasElement);
       Const Fmt : String; Args : Array of const; PosEl: TPasElement);
     procedure LogMsg(const id: int64; MsgType: TMessageType; MsgNumber: integer;
     procedure LogMsg(const id: int64; MsgType: TMessageType; MsgNumber: integer;
       const Fmt: String; Args: Array of const; PosEl: TPasElement); overload;
       const Fmt: String; Args: Array of const; PosEl: TPasElement); overload;
+    procedure GetIncompatibleTypeDesc(const GotType, ExpType: TPasResolverResult;
+      out GotDesc, ExpDesc: String);
     procedure RaiseMsg(const Id: int64; MsgNumber: integer; const Fmt: String;
     procedure RaiseMsg(const Id: int64; MsgNumber: integer; const Fmt: String;
       Args: Array of const; ErrorPosEl: TPasElement);
       Args: Array of const; ErrorPosEl: TPasElement);
     procedure RaiseNotYetImplemented(id: int64; El: TPasElement; Msg: string = ''); virtual;
     procedure RaiseNotYetImplemented(id: int64; El: TPasElement; Msg: string = ''); virtual;
@@ -1574,6 +1576,7 @@ function GetTreeDbg(El: TPasElement; Indent: integer = 0): string;
 function GetResolverResultDbg(const T: TPasResolverResult): string;
 function GetResolverResultDbg(const T: TPasResolverResult): string;
 function GetClassAncestorsDbg(El: TPasClassType): string;
 function GetClassAncestorsDbg(El: TPasClassType): string;
 function ResolverResultFlagsToStr(const Flags: TPasResolverResultFlags): string;
 function ResolverResultFlagsToStr(const Flags: TPasResolverResultFlags): string;
+function GetElementTypeName(El: TPasElement): string;
 
 
 procedure SetResolverIdentifier(out ResolvedType: TPasResolverResult;
 procedure SetResolverIdentifier(out ResolvedType: TPasResolverResult;
   BaseType: TResolverBaseType; IdentEl: TPasElement;
   BaseType: TResolverBaseType; IdentEl: TPasElement;
@@ -1806,6 +1809,83 @@ begin
   Result:='['+Result+']';
   Result:='['+Result+']';
 end;
 end;
 
 
+function GetElementTypeName(El: TPasElement): string;
+var
+  C: TClass;
+begin
+  if El=nil then
+    exit('?');
+  C:=El.ClassType;
+  if C=TPasAliasType then
+    Result:='alias'
+  else if C=TPasPointerType then
+    Result:='pointer of'
+  else if C=TPasTypeAliasType then
+    Result:='type alias'
+  else if C=TPasClassOfType then
+    Result:='class of'
+  else if C=TPasSpecializeType then
+    Result:='specialize'
+  else if C=TInlineSpecializeExpr then
+    Result:='inline specialize'
+  else if C=TPasRangeType then
+    Result:='range'
+  else if C=TPasArrayType then
+    Result:='array'
+  else if C=TPasFileType then
+    Result:='file of'
+  else if C=TPasEnumValue then
+    Result:='enum value'
+  else if C=TPasEnumType then
+    Result:='enum type'
+  else if C=TPasSetType then
+    Result:='set'
+  else if C=TPasRecordType then
+    Result:='record'
+  else if C=TPasClassType then
+    Result:='class'
+  else if C=TPasArgument then
+    Result:='parameter'
+  else if C=TPasProcedureType then
+    Result:='procedural type'
+  else if C=TPasResultElement then
+    Result:='function result'
+  else if C=TPasFunctionType then
+    Result:='functional type'
+  else if C=TPasStringType then
+    Result:='string'
+  else if C=TPasVariable then
+    Result:='var'
+  else if C=TPasExportSymbol then
+    Result:='export'
+  else if C=TPasConst then
+    Result:='const'
+  else if C=TPasProperty then
+    Result:='property'
+  else if C=TPasProcedure then
+    Result:='procedure'
+  else if C=TPasFunction then
+    Result:='function'
+  else if C=TPasOperator then
+    Result:='operator'
+  else if C=TPasClassOperator then
+    Result:='class operator'
+  else if C=TPasConstructor then
+    Result:='constructor'
+  else if C=TPasClassConstructor then
+    Result:='class constructor'
+  else if C=TPasDestructor then
+    Result:='destructor'
+  else if C=TPasClassDestructor then
+    Result:='class destructor'
+  else if C=TPasClassProcedure then
+    Result:='class procedure'
+  else if C=TPasClassFunction then
+    Result:='class function'
+  else
+    Result:=El.ElementTypeName;
+end;
+
 procedure SetResolverIdentifier(out ResolvedType: TPasResolverResult;
 procedure SetResolverIdentifier(out ResolvedType: TPasResolverResult;
   BaseType: TResolverBaseType; IdentEl: TPasElement; TypeEl: TPasType;
   BaseType: TResolverBaseType; IdentEl: TPasElement; TypeEl: TPasType;
   Flags: TPasResolverResultFlags);
   Flags: TPasResolverResultFlags);
@@ -3265,7 +3345,7 @@ var
   end;
   end;
 
 
 begin
 begin
-  //writeln('TPasResolver.OnFindOverloadProc START ',El.Name,':',El.ElementTypeName,' itself=',El=Data^.Proc);
+  //writeln('TPasResolver.OnFindOverloadProc START ',El.Name,':',GetElementTypeName(El),' itself=',El=Data^.Proc);
   if not (El is TPasProcedure) then
   if not (El is TPasProcedure) then
     begin
     begin
     // identifier is not a proc
     // identifier is not a proc
@@ -3626,7 +3706,7 @@ begin
     else if (UseModule.ClassType=TPasModule) then
     else if (UseModule.ClassType=TPasModule) then
       PublicEl:=TPasModule(UseModule).InterfaceSection
       PublicEl:=TPasModule(UseModule).InterfaceSection
     else
     else
-      RaiseXExpectedButYFound(20170503004803,'unit',UseModule.ElementTypeName,UseUnit);
+      RaiseXExpectedButYFound(20170503004803,'unit',GetElementTypeName(UseModule),UseUnit);
     if PublicEl=nil then
     if PublicEl=nil then
       RaiseInternalError(20160922163352,'uses element has no interface section: '+GetObjName(UseModule));
       RaiseInternalError(20160922163352,'uses element has no interface section: '+GetObjName(UseModule));
     if PublicEl.CustomData=nil then
     if PublicEl.CustomData=nil then
@@ -3744,7 +3824,7 @@ procedure TPasResolver.FinishTypeSection(El: TPasDeclarations);
       else
       else
         exit(false);
         exit(false);
     if Data.Found.ClassType<>TPasClassType then
     if Data.Found.ClassType<>TPasClassType then
-      RaiseXExpectedButYFound(20170216151548,'class',Data.Found.ElementTypeName,ErrorEl);
+      RaiseXExpectedButYFound(20170216151548,'class',GetElementTypeName(Data.Found),ErrorEl);
     // replace unresolved
     // replace unresolved
     OldDestType:=AliasType.DestType;
     OldDestType:=AliasType.DestType;
     AliasType.DestType:=TPasType(Data.Found);
     AliasType.DestType:=TPasType(Data.Found);
@@ -3872,10 +3952,10 @@ begin
       BaseTypeData:=TResElDataBaseType(EnumType.CustomData);
       BaseTypeData:=TResElDataBaseType(EnumType.CustomData);
       if BaseTypeData.BaseType in (btAllChars+[btBoolean,btByte]) then
       if BaseTypeData.BaseType in (btAllChars+[btBoolean,btByte]) then
         exit;
         exit;
-      RaiseXExpectedButYFound(20170216151553,'char or boolean',EnumType.ElementTypeName,EnumType);
+      RaiseXExpectedButYFound(20170216151553,'char or boolean',GetElementTypeName(EnumType),EnumType);
       end;
       end;
     end;
     end;
-  RaiseXExpectedButYFound(20170216151557,'enum type',EnumType.ElementTypeName,EnumType);
+  RaiseXExpectedButYFound(20170216151557,'enum type',GetElementTypeName(EnumType),EnumType);
 end;
 end;
 
 
 procedure TPasResolver.FinishSubElementType(Parent: TPasElement; El: TPasType);
 procedure TPasResolver.FinishSubElementType(Parent: TPasElement; El: TPasType);
@@ -3886,9 +3966,9 @@ begin
   EmitTypeHints(Parent,El);
   EmitTypeHints(Parent,El);
   if (El.Name<>'') or (AnonymousElTypePostfix='') then exit;
   if (El.Name<>'') or (AnonymousElTypePostfix='') then exit;
   if Parent.Name='' then
   if Parent.Name='' then
-    RaiseMsg(20170415165455,nCannotNestAnonymousX,sCannotNestAnonymousX,[El.ElementTypeName],El);
+    RaiseMsg(20170415165455,nCannotNestAnonymousX,sCannotNestAnonymousX,[GetElementTypeName(El)],El);
   if not (Parent.Parent is TPasDeclarations) then
   if not (Parent.Parent is TPasDeclarations) then
-    RaiseMsg(20170416094735,nCannotNestAnonymousX,sCannotNestAnonymousX,[El.ElementTypeName],El);
+    RaiseMsg(20170416094735,nCannotNestAnonymousX,sCannotNestAnonymousX,[GetElementTypeName(El)],El);
   // give anonymous sub type a name
   // give anonymous sub type a name
   El.Name:=Parent.Name+AnonymousElTypePostfix;
   El.Name:=Parent.Name+AnonymousElTypePostfix;
   {$IFDEF VerbosePasResolver}
   {$IFDEF VerbosePasResolver}
@@ -3980,7 +4060,7 @@ begin
     ResolveExpr(Expr,rraRead);
     ResolveExpr(Expr,rraRead);
     ComputeElement(Expr,RangeResolved,[rcConstant]);
     ComputeElement(Expr,RangeResolved,[rcConstant]);
     if (RangeResolved.IdentEl<>nil) and not (RangeResolved.IdentEl is TPasType) then
     if (RangeResolved.IdentEl<>nil) and not (RangeResolved.IdentEl is TPasType) then
-      RaiseXExpectedButYFound(20170216151607,'range',RangeResolved.IdentEl.ElementTypeName,Expr);
+      RaiseXExpectedButYFound(20170216151607,'range',GetElementTypeName(RangeResolved.IdentEl),Expr);
     if (RangeResolved.BaseType=btRange) then
     if (RangeResolved.BaseType=btRange) then
       begin
       begin
       if (RangeResolved.SubType in btArrayRangeTypes) then
       if (RangeResolved.SubType in btArrayRangeTypes) then
@@ -3991,17 +4071,17 @@ begin
         if TypeEl is TPasRangeType then
         if TypeEl is TPasRangeType then
           // custom range
           // custom range
         else
         else
-          RaiseXExpectedButYFound(20171009193629,'range',RangeResolved.IdentEl.ElementTypeName,Expr);
+          RaiseXExpectedButYFound(20171009193629,'range',GetElementTypeName(RangeResolved.IdentEl),Expr);
         end
         end
       else
       else
-        RaiseXExpectedButYFound(20171009193514,'range',RangeResolved.IdentEl.ElementTypeName,Expr);
+        RaiseXExpectedButYFound(20171009193514,'range',GetElementTypeName(RangeResolved.IdentEl),Expr);
       end
       end
     else if RangeResolved.BaseType in btArrayRangeTypes then
     else if RangeResolved.BaseType in btArrayRangeTypes then
       // full range, e.g. array[char]
       // full range, e.g. array[char]
     else if (RangeResolved.BaseType=btContext) and (RangeResolved.TypeEl is TPasEnumType) then
     else if (RangeResolved.BaseType=btContext) and (RangeResolved.TypeEl is TPasEnumType) then
       // e.g. array[enumtype]
       // e.g. array[enumtype]
     else
     else
-      RaiseXExpectedButYFound(20170216151609,'range',RangeResolved.IdentEl.ElementTypeName,Expr);
+      RaiseXExpectedButYFound(20170216151609,'range',GetElementTypeName(RangeResolved.IdentEl),Expr);
     end;
     end;
   if El.ElType=nil then
   if El.ElType=nil then
     RaiseNotYetImplemented(20171005235610,El,'array of const');
     RaiseNotYetImplemented(20171005235610,El,'array of const');
@@ -4050,7 +4130,7 @@ begin
         SubProcScope:=TPasProcedure(SubEl).CustomData as TPasProcedureScope;
         SubProcScope:=TPasProcedure(SubEl).CustomData as TPasProcedureScope;
         if SubProcScope.ImplProc=nil then
         if SubProcScope.ImplProc=nil then
           RaiseMsg(20170216151613,nForwardProcNotResolved,sForwardProcNotResolved,
           RaiseMsg(20170216151613,nForwardProcNotResolved,sForwardProcNotResolved,
-            [SubEl.ElementTypeName,SubEl.Name],SubEl);
+            [GetElementTypeName(SubEl),SubEl.Name],SubEl);
         end;
         end;
       end;
       end;
     end;
     end;
@@ -4109,11 +4189,11 @@ begin
                        pmExternal, pmDispId,
                        pmExternal, pmDispId,
                        pmfar]) then
                        pmfar]) then
           RaiseMsg(20170216151616,nInvalidXModifierY,
           RaiseMsg(20170216151616,nInvalidXModifierY,
-            sInvalidXModifierY,[Proc.ElementTypeName,'external, '+ModifierNames[pm]],Proc);
+            sInvalidXModifierY,[GetElementTypeName(Proc),'external, '+ModifierNames[pm]],Proc);
       for ptm in Proc.ProcType.Modifiers do
       for ptm in Proc.ProcType.Modifiers do
         if not (ptm in [ptmOfObject,ptmIsNested,ptmStatic,ptmVarargs,ptmReferenceTo]) then
         if not (ptm in [ptmOfObject,ptmIsNested,ptmStatic,ptmVarargs,ptmReferenceTo]) then
           RaiseMsg(20170411171224,nInvalidXModifierY,
           RaiseMsg(20170411171224,nInvalidXModifierY,
-            sInvalidXModifierY,[Proc.ElementTypeName,'external, '+ProcTypeModifiers[ptm]],Proc);
+            sInvalidXModifierY,[GetElementTypeName(Proc),'external, '+ProcTypeModifiers[ptm]],Proc);
       end;
       end;
 
 
     HasDots:=Pos('.',ProcName)>1;
     HasDots:=Pos('.',ProcName)>1;
@@ -4124,19 +4204,19 @@ begin
       if Proc.IsAbstract then
       if Proc.IsAbstract then
         begin
         begin
         if not Proc.IsVirtual then
         if not Proc.IsVirtual then
-          RaiseMsg(20170216151623,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'abstract without virtual'],Proc);
+          RaiseMsg(20170216151623,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'abstract without virtual'],Proc);
         if Proc.IsOverride then
         if Proc.IsOverride then
-          RaiseMsg(20170216151625,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'abstract, override'],Proc);
+          RaiseMsg(20170216151625,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'abstract, override'],Proc);
         end;
         end;
       if Proc.IsVirtual and Proc.IsOverride then
       if Proc.IsVirtual and Proc.IsOverride then
-        RaiseMsg(20170216151627,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'virtual, override'],Proc);
+        RaiseMsg(20170216151627,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'virtual, override'],Proc);
       if Proc.IsReintroduced and Proc.IsOverride then
       if Proc.IsReintroduced and Proc.IsOverride then
-        RaiseMsg(20171119111845,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'reintroduce, override'],Proc);
+        RaiseMsg(20171119111845,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'reintroduce, override'],Proc);
       if Proc.IsForward then
       if Proc.IsForward then
-        RaiseMsg(20170216151629,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'forward'],Proc);
+        RaiseMsg(20170216151629,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'forward'],Proc);
       if Proc.IsStatic then
       if Proc.IsStatic then
         if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
         if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
-          RaiseMsg(20170216151631,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'static'],Proc);
+          RaiseMsg(20170216151631,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'static'],Proc);
       end
       end
     else
     else
       begin
       begin
@@ -4364,9 +4444,9 @@ var
   p: Integer;
   p: Integer;
 begin
 begin
   if ImplProc.IsExternal then
   if ImplProc.IsExternal then
-    RaiseMsg(20170216151715,nInvalidXModifierY,sInvalidXModifierY,[ImplProc.ElementTypeName,'external'],ImplProc);
+    RaiseMsg(20170216151715,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(ImplProc),'external'],ImplProc);
   if ImplProc.IsExported then
   if ImplProc.IsExported then
-    RaiseMsg(20170216151717,nInvalidXModifierY,sInvalidXModifierY,[ImplProc.ElementTypeName,'export'],ImplProc);
+    RaiseMsg(20170216151717,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(ImplProc),'export'],ImplProc);
 
 
   ProcName:=ImplProc.Name;
   ProcName:=ImplProc.Name;
   {$IFDEF VerbosePasResolver}
   {$IFDEF VerbosePasResolver}
@@ -4575,7 +4655,7 @@ var
         RaiseMsg(20170216151741,nNoPropertyFoundToOverride,sNoPropertyFoundToOverride,[],PropEl);
         RaiseMsg(20170216151741,nNoPropertyFoundToOverride,sNoPropertyFoundToOverride,[],PropEl);
       // check property versus class property
       // check property versus class property
       if PropEl.ClassType<>AncestorProp.ClassType then
       if PropEl.ClassType<>AncestorProp.ClassType then
-        RaiseXExpectedButYFound(20170216151744,AncestorProp.ElementTypeName,PropEl.ElementTypeName,PropEl);
+        RaiseXExpectedButYFound(20170216151744,GetElementTypeName(AncestorProp),GetElementTypeName(PropEl),PropEl);
       // get inherited type
       // get inherited type
       PropType:=GetPasPropertyType(AncestorProp);
       PropType:=GetPasPropertyType(AncestorProp);
       // update DefaultProperty
       // update DefaultProperty
@@ -4605,7 +4685,7 @@ var
           RaiseIdentifierNotFound(20170216151749,Prim.Value,Prim);
           RaiseIdentifierNotFound(20170216151749,Prim.Value,Prim);
         DeclEl:=Identifier.Element;
         DeclEl:=Identifier.Element;
         if DeclEl.ClassType<>TPasClassType then
         if DeclEl.ClassType<>TPasClassType then
-          RaiseXExpectedButYFound(20170216151752,'class',DeclEl.ElementTypeName,Prim);
+          RaiseXExpectedButYFound(20170216151752,'class',GetElementTypeName(DeclEl),Prim);
         CreateReference(DeclEl,Prim,rraRead);
         CreateReference(DeclEl,Prim,rraRead);
         end
         end
       else
       else
@@ -4688,11 +4768,11 @@ var
         begin
         begin
         if ProcArg.ArgType<>nil then
         if ProcArg.ArgType<>nil then
           RaiseMsg(20170216151811,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
           RaiseMsg(20170216151811,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
-            [IntToStr(ArgNo),ProcArg.ArgType.ElementTypeName,'untyped'],ErrorEl);
+            [IntToStr(ArgNo),GetElementTypeName(ProcArg.ArgType),'untyped'],ErrorEl);
         end
         end
       else if ProcArg.ArgType=nil then
       else if ProcArg.ArgType=nil then
         RaiseMsg(20170216151813,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
         RaiseMsg(20170216151813,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
-          [IntToStr(ArgNo),'untyped',PropArg.ArgType.ElementTypeName],ErrorEl)
+          [IntToStr(ArgNo),'untyped',GetElementTypeName(PropArg.ArgType)],ErrorEl)
       else
       else
         begin
         begin
         ComputeElement(PropArg,PropArgResolved,[rcNoImplicitProc]);
         ComputeElement(PropArg,PropArgResolved,[rcNoImplicitProc]);
@@ -4742,9 +4822,9 @@ var
       Proc:=TPasProcedure(IdentEl);
       Proc:=TPasProcedure(IdentEl);
       // check if member
       // check if member
       if not (Expr is TPrimitiveExpr) then
       if not (Expr is TPrimitiveExpr) then
-        RaiseXExpectedButYFound(20170923202002,'member function','foreign '+Proc.ElementTypeName,Expr);
+        RaiseXExpectedButYFound(20170923202002,'member function','foreign '+GetElementTypeName(Proc),Expr);
       if Proc.ClassType<>TPasFunction then
       if Proc.ClassType<>TPasFunction then
-        RaiseXExpectedButYFound(20170216151925,'function',Proc.ElementTypeName,Expr);
+        RaiseXExpectedButYFound(20170216151925,'function',GetElementTypeName(Proc),Expr);
       // check function result type
       // check function result type
       ResultType:=TPasFunction(Proc).FuncType.ResultEl.ResultType;
       ResultType:=TPasFunction(Proc).FuncType.ResultEl.ResultType;
       if not IsBaseType(ResultType,btBoolean,true) then
       if not IsBaseType(ResultType,btBoolean,true) then
@@ -4773,7 +4853,7 @@ var
       aVar:=TPasVariable(IdentEl);
       aVar:=TPasVariable(IdentEl);
       // check if member
       // check if member
       if not (Expr is TPrimitiveExpr) then
       if not (Expr is TPrimitiveExpr) then
-        RaiseXExpectedButYFound(20170923202003,'member variable','foreign '+aVar.ElementTypeName,Expr);
+        RaiseXExpectedButYFound(20170923202003,'member variable','foreign '+GetElementTypeName(aVar),Expr);
       // check type boolean
       // check type boolean
       TypeEl:=aVar.VarType;
       TypeEl:=aVar.VarType;
       TypeEl:=ResolveAliasType(TypeEl);
       TypeEl:=ResolveAliasType(TypeEl);
@@ -4901,7 +4981,7 @@ begin
       if (AccEl.ClassType=TPasVariable) or (AccEl.ClassType=TPasConst) then
       if (AccEl.ClassType=TPasVariable) or (AccEl.ClassType=TPasConst) then
         begin
         begin
         if (PropEl.Args.Count>0) then
         if (PropEl.Args.Count>0) then
-          RaiseXExpectedButYFound(20170216151823,'function',AccEl.ElementTypeName,PropEl.ReadAccessor);
+          RaiseXExpectedButYFound(20170216151823,'function',GetElementTypeName(AccEl),PropEl.ReadAccessor);
         if not IsSameType(TPasVariable(AccEl).VarType,PropType,true) then
         if not IsSameType(TPasVariable(AccEl).VarType,PropType,true) then
           RaiseIncompatibleType(20170216151826,nIncompatibleTypesGotExpected,
           RaiseIncompatibleType(20170216151826,nIncompatibleTypesGotExpected,
             [],PropType,TPasVariable(AccEl).VarType,PropEl.ReadAccessor);
             [],PropType,TPasVariable(AccEl).VarType,PropEl.ReadAccessor);
@@ -4918,7 +4998,7 @@ begin
         if (vmClass in PropEl.VarModifiers) then
         if (vmClass in PropEl.VarModifiers) then
           begin
           begin
           if Proc.ClassType<>TPasClassFunction then
           if Proc.ClassType<>TPasClassFunction then
-            RaiseXExpectedButYFound(20170216151834,'class function',Proc.ElementTypeName,PropEl.ReadAccessor);
+            RaiseXExpectedButYFound(20170216151834,'class function',GetElementTypeName(Proc),PropEl.ReadAccessor);
           if Proc.IsStatic=(proClassPropertyNonStatic in Options) then
           if Proc.IsStatic=(proClassPropertyNonStatic in Options) then
             if Proc.IsStatic then
             if Proc.IsStatic then
               RaiseMsg(20170216151837,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.ReadAccessor)
               RaiseMsg(20170216151837,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.ReadAccessor)
@@ -4928,7 +5008,7 @@ begin
         else
         else
           begin
           begin
           if Proc.ClassType<>TPasFunction then
           if Proc.ClassType<>TPasFunction then
-            RaiseXExpectedButYFound(20170216151842,'function',Proc.ElementTypeName,PropEl.ReadAccessor);
+            RaiseXExpectedButYFound(20170216151842,'function',GetElementTypeName(Proc),PropEl.ReadAccessor);
           end;
           end;
         // check function result type
         // check function result type
         ResultType:=TPasFunction(Proc).FuncType.ResultEl.ResultType;
         ResultType:=TPasFunction(Proc).FuncType.ResultEl.ResultType;
@@ -4945,7 +5025,7 @@ begin
             [Proc.Name],PropEl.ReadAccessor);
             [Proc.Name],PropEl.ReadAccessor);
         end
         end
       else
       else
-        RaiseXExpectedButYFound(20170216151850,'variable',AccEl.ElementTypeName,PropEl.ReadAccessor);
+        RaiseXExpectedButYFound(20170216151850,'variable',GetElementTypeName(AccEl),PropEl.ReadAccessor);
       end;
       end;
 
 
     if PropEl.WriteAccessor<>nil then
     if PropEl.WriteAccessor<>nil then
@@ -4956,7 +5036,7 @@ begin
           or ((AccEl.ClassType=TPasConst) and (not TPasConst(AccEl).IsConst)) then
           or ((AccEl.ClassType=TPasConst) and (not TPasConst(AccEl).IsConst)) then
         begin
         begin
         if (PropEl.Args.Count>0) then
         if (PropEl.Args.Count>0) then
-          RaiseXExpectedButYFound(20170216151852,'procedure',AccEl.ElementTypeName,PropEl.WriteAccessor);
+          RaiseXExpectedButYFound(20170216151852,'procedure',GetElementTypeName(AccEl),PropEl.WriteAccessor);
         if not IsSameType(TPasVariable(AccEl).VarType,PropType,true) then
         if not IsSameType(TPasVariable(AccEl).VarType,PropType,true) then
           RaiseIncompatibleType(20170216151855,nIncompatibleTypesGotExpected,
           RaiseIncompatibleType(20170216151855,nIncompatibleTypesGotExpected,
             [],PropType,TPasVariable(AccEl).VarType,PropEl.WriteAccessor);
             [],PropType,TPasVariable(AccEl).VarType,PropEl.WriteAccessor);
@@ -4973,7 +5053,7 @@ begin
         if (vmClass in PropEl.VarModifiers) then
         if (vmClass in PropEl.VarModifiers) then
           begin
           begin
           if Proc.ClassType<>TPasClassProcedure then
           if Proc.ClassType<>TPasClassProcedure then
-            RaiseXExpectedButYFound(20170216151903,'class procedure',Proc.ElementTypeName,PropEl.WriteAccessor);
+            RaiseXExpectedButYFound(20170216151903,'class procedure',GetElementTypeName(Proc),PropEl.WriteAccessor);
             if Proc.IsStatic=(proClassPropertyNonStatic in Options) then
             if Proc.IsStatic=(proClassPropertyNonStatic in Options) then
               if Proc.IsStatic then
               if Proc.IsStatic then
                 RaiseMsg(20170216151905,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.WriteAccessor)
                 RaiseMsg(20170216151905,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.WriteAccessor)
@@ -4983,7 +5063,7 @@ begin
         else
         else
           begin
           begin
           if Proc.ClassType<>TPasProcedure then
           if Proc.ClassType<>TPasProcedure then
-            RaiseXExpectedButYFound(20170216151910,'procedure',Proc.ElementTypeName,PropEl.WriteAccessor);
+            RaiseXExpectedButYFound(20170216151910,'procedure',GetElementTypeName(Proc),PropEl.WriteAccessor);
           end;
           end;
         // check args
         // check args
         CheckArgs(Proc,IndexVal,IndexResolved,PropEl.ReadAccessor);
         CheckArgs(Proc,IndexVal,IndexResolved,PropEl.ReadAccessor);
@@ -5004,7 +5084,7 @@ begin
             [IntToStr(PropArgCount+1)],Arg.ArgType,PropType,PropEl.WriteAccessor);
             [IntToStr(PropArgCount+1)],Arg.ArgType,PropType,PropEl.WriteAccessor);
         end
         end
       else
       else
-        RaiseXExpectedButYFound(20170216151921,'variable',AccEl.ElementTypeName,PropEl.WriteAccessor);
+        RaiseXExpectedButYFound(20170216151921,'variable',GetElementTypeName(AccEl),PropEl.WriteAccessor);
       end;
       end;
 
 
     if PropEl.ImplementsFunc<>nil then
     if PropEl.ImplementsFunc<>nil then
@@ -5748,7 +5828,7 @@ begin
       end
       end
     else
     else
       RaiseMsg(20170216152007,nExprTypeMustBeClassOrRecordTypeGot,sExprTypeMustBeClassOrRecordTypeGot,
       RaiseMsg(20170216152007,nExprTypeMustBeClassOrRecordTypeGot,sExprTypeMustBeClassOrRecordTypeGot,
-        [TypeEl.ElementTypeName],ErrorEl);
+        [GetElementTypeName(TypeEl)],ErrorEl);
     WithExprScope:=ScopeClass_WithExpr.Create;
     WithExprScope:=ScopeClass_WithExpr.Create;
     WithExprScope.WithScope:=WithScope;
     WithExprScope.WithScope:=WithScope;
     WithExprScope.Index:=i;
     WithExprScope.Index:=i;
@@ -5902,7 +5982,7 @@ begin
         writeln('TPasResolver.ResolveImplRaise ',GetResolverResultDbg(ResolvedEl));
         writeln('TPasResolver.ResolveImplRaise ',GetResolverResultDbg(ResolvedEl));
         {$ENDIF}
         {$ENDIF}
         RaiseMsg(20170216152133,nXExpectedButYFound,sXExpectedButYFound,
         RaiseMsg(20170216152133,nXExpectedButYFound,sXExpectedButYFound,
-                 ['variable',ResolvedEl.IdentEl.ElementTypeName],El.ExceptObject);
+                 ['variable',GetElementTypeName(ResolvedEl.IdentEl)],El.ExceptObject);
         end;
         end;
       end
       end
     else if ResolvedEl.ExprEl<>nil then
     else if ResolvedEl.ExprEl<>nil then
@@ -6298,7 +6378,7 @@ begin
     end
     end
   else
   else
     RaiseMsg(20170216152541,nExprTypeMustBeClassOrRecordTypeGot,sExprTypeMustBeClassOrRecordTypeGot,
     RaiseMsg(20170216152541,nExprTypeMustBeClassOrRecordTypeGot,sExprTypeMustBeClassOrRecordTypeGot,
-      [LeftResolved.TypeEl.ElementTypeName],El);
+      [GetElementTypeName(LeftResolved.TypeEl)],El);
 
 
   {$IFDEF VerbosePasResolver}
   {$IFDEF VerbosePasResolver}
   writeln('TPasResolver.ResolveSubIdent left=',GetObjName(Left),' right=',GetObjName(El.right),' leftresolved=',GetResolverResultDbg(LeftResolved));
   writeln('TPasResolver.ResolveSubIdent left=',GetObjName(Left),' right=',GetObjName(El.right),' leftresolved=',GetResolverResultDbg(LeftResolved));
@@ -6665,7 +6745,7 @@ begin
     begin
     begin
     // string -> check that ResolvedValue is not merely a type, but has a value
     // string -> check that ResolvedValue is not merely a type, but has a value
     if not (rrfReadable in ResolvedValue.Flags) then
     if not (rrfReadable in ResolvedValue.Flags) then
-      RaiseXExpectedButYFound(20170216152548,'variable',ResolvedValue.TypeEl.ElementTypeName,Params);
+      RaiseXExpectedButYFound(20170216152548,'variable',GetElementTypeName(ResolvedValue.TypeEl),Params);
     // check single argument
     // check single argument
     if length(Params.Params)<1 then
     if length(Params.Params)<1 then
       RaiseMsg(20170216152204,nMissingParameterX,
       RaiseMsg(20170216152204,nMissingParameterX,
@@ -6878,7 +6958,7 @@ begin
         if ProcNeedsImplProc(Proc)
         if ProcNeedsImplProc(Proc)
             and (TPasProcedureScope(Proc.CustomData).ImplProc=nil) then
             and (TPasProcedureScope(Proc.CustomData).ImplProc=nil) then
           RaiseMsg(20170216152219,nForwardProcNotResolved,sForwardProcNotResolved,
           RaiseMsg(20170216152219,nForwardProcNotResolved,sForwardProcNotResolved,
-            [Proc.ElementTypeName,Proc.Name],Proc);
+            [GetElementTypeName(Proc),Proc.Name],Proc);
         end;
         end;
       end;
       end;
     end
     end
@@ -6894,7 +6974,7 @@ begin
         if Proc.IsAbstract or Proc.IsExternal then continue;
         if Proc.IsAbstract or Proc.IsExternal then continue;
         if TPasProcedureScope(Proc.CustomData).ImplProc=nil then
         if TPasProcedureScope(Proc.CustomData).ImplProc=nil then
           RaiseMsg(20170216152221,nForwardProcNotResolved,sForwardProcNotResolved,
           RaiseMsg(20170216152221,nForwardProcNotResolved,sForwardProcNotResolved,
-            [Proc.ElementTypeName,Proc.Name],Proc);
+            [GetElementTypeName(Proc),Proc.Name],Proc);
         end;
         end;
       end;
       end;
     end;
     end;
@@ -7155,7 +7235,7 @@ begin
       if not (CurClassType is TPasClassType) then
       if not (CurClassType is TPasClassType) then
         begin
         begin
         aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName));
         aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName));
-        RaiseXExpectedButYFound(20170216152557,'class',aClassname+':'+CurClassType.ElementTypeName,El);
+        RaiseXExpectedButYFound(20170216152557,'class',aClassname+':'+GetElementTypeName(CurClassType),El);
         end;
         end;
 
 
       // restore scope
       // restore scope
@@ -7553,7 +7633,7 @@ begin
         if LeftResolved.BaseType in (btAllInteger+btAllChars) then
         if LeftResolved.BaseType in (btAllInteger+btAllChars) then
           begin
           begin
           if (RightResolved.BaseType<>btSet) then
           if (RightResolved.BaseType<>btSet) then
-            RaiseXExpectedButYFound(20170216152607,'set of '+BaseTypeNames[LeftResolved.BaseType],LeftResolved.TypeEl.ElementTypeName,Bin.right);
+            RaiseXExpectedButYFound(20170216152607,'set of '+BaseTypeNames[LeftResolved.BaseType],GetElementTypeName(LeftResolved.TypeEl),Bin.right);
           if LeftResolved.BaseType in btAllChars then
           if LeftResolved.BaseType in btAllChars then
             begin
             begin
             if not (RightResolved.SubType in btAllChars) then
             if not (RightResolved.SubType in btAllChars) then
@@ -7567,7 +7647,7 @@ begin
         else if (LeftResolved.BaseType=btContext) and (LeftResolved.TypeEl is TPasEnumType) then
         else if (LeftResolved.BaseType=btContext) and (LeftResolved.TypeEl is TPasEnumType) then
           begin
           begin
           if (RightResolved.BaseType<>btSet) then
           if (RightResolved.BaseType<>btSet) then
-            RaiseXExpectedButYFound(20170216152615,'set of '+LeftResolved.TypeEl.Name,LeftResolved.TypeEl.ElementTypeName,Bin.right);
+            RaiseXExpectedButYFound(20170216152615,'set of '+LeftResolved.TypeEl.Name,GetElementTypeName(LeftResolved.TypeEl),Bin.right);
           if LeftResolved.TypeEl=RightResolved.TypeEl then
           if LeftResolved.TypeEl=RightResolved.TypeEl then
           else if RightResolved.TypeEl.ClassType=TPasRangeType then
           else if RightResolved.TypeEl.ClassType=TPasRangeType then
             begin
             begin
@@ -7582,7 +7662,7 @@ begin
           end
           end
         else
         else
           RaiseMsg(20170216152228,nInOperatorExpectsSetElementButGot,
           RaiseMsg(20170216152228,nInOperatorExpectsSetElementButGot,
-            sInOperatorExpectsSetElementButGot,[LeftResolved.TypeEl.ElementTypeName],Bin);
+            sInOperatorExpectsSetElementButGot,[GetElementTypeName(LeftResolved.TypeEl)],Bin);
         end;
         end;
     eopIs:
     eopIs:
       begin
       begin
@@ -7591,7 +7671,8 @@ begin
       if (LeftTypeEl is TPasClassType) then
       if (LeftTypeEl is TPasClassType) then
         begin
         begin
         if (LeftResolved.IdentEl=nil) or (LeftResolved.IdentEl is TPasType) then
         if (LeftResolved.IdentEl=nil) or (LeftResolved.IdentEl is TPasType) then
-          RaiseMsg(20170216152230,nIllegalQualifier,sIllegalQualifier,['is'],Bin);
+          RaiseIncompatibleTypeRes(20180204124638,nOperatorIsNotOverloadedAOpB,
+            [OpcodeStrings[Bin.OpCode]],LeftResolved,RightResolved,Bin);
         // left side is a class instance
         // left side is a class instance
         if (RightResolved.IdentEl is TPasType)
         if (RightResolved.IdentEl is TPasType)
             and (ResolveAliasType(TPasType(RightResolved.IdentEl)) is TPasClassType) then
             and (ResolveAliasType(TPasType(RightResolved.IdentEl)) is TPasClassType) then
@@ -7627,13 +7708,14 @@ begin
             end;
             end;
           end
           end
         else
         else
-          RaiseXExpectedButYFound(20170216152625,'class type',RightResolved.TypeEl.ElementTypeName,Bin.right);
+          RaiseXExpectedButYFound(20170216152625,'class type',GetElementTypeName(RightResolved.TypeEl),Bin.right);
         end
         end
       else if (proClassOfIs in Options) and (LeftTypeEl is TPasClassOfType)
       else if (proClassOfIs in Options) and (LeftTypeEl is TPasClassOfType)
           and (rrfReadable in LeftResolved.Flags) then
           and (rrfReadable in LeftResolved.Flags) then
         begin
         begin
         if (LeftResolved.IdentEl=nil) or (LeftResolved.IdentEl is TPasType) then
         if (LeftResolved.IdentEl=nil) or (LeftResolved.IdentEl is TPasType) then
-          RaiseMsg(20170322101128,nIllegalQualifier,sIllegalQualifier,['is'],Bin);
+          RaiseIncompatibleTypeRes(20180204124657,nOperatorIsNotOverloadedAOpB,
+            [OpcodeStrings[Bin.OpCode]],LeftResolved,RightResolved,Bin);
         // left side is class-of variable
         // left side is class-of variable
         LeftTypeEl:=ResolveAliasType(TPasClassOfType(LeftResolved.TypeEl).DestType);
         LeftTypeEl:=ResolveAliasType(TPasClassOfType(LeftResolved.TypeEl).DestType);
         if (RightResolved.IdentEl is TPasType)
         if (RightResolved.IdentEl is TPasType)
@@ -7659,14 +7741,14 @@ begin
             end
             end
           end
           end
         else
         else
-          RaiseXExpectedButYFound(20170322105252,'class type',RightResolved.TypeEl.ElementTypeName,Bin.right);
+          RaiseXExpectedButYFound(20170322105252,'class type',GetElementTypeName(RightResolved.TypeEl),Bin.right);
         end
         end
       else if LeftResolved.TypeEl=nil then
       else if LeftResolved.TypeEl=nil then
         RaiseMsg(20170216152232,nLeftSideOfIsOperatorExpectsAClassButGot,sLeftSideOfIsOperatorExpectsAClassButGot,
         RaiseMsg(20170216152232,nLeftSideOfIsOperatorExpectsAClassButGot,sLeftSideOfIsOperatorExpectsAClassButGot,
                  [BaseTypeNames[LeftResolved.BaseType]],Bin.left)
                  [BaseTypeNames[LeftResolved.BaseType]],Bin.left)
       else
       else
         RaiseMsg(20170216152234,nLeftSideOfIsOperatorExpectsAClassButGot,sLeftSideOfIsOperatorExpectsAClassButGot,
         RaiseMsg(20170216152234,nLeftSideOfIsOperatorExpectsAClassButGot,sLeftSideOfIsOperatorExpectsAClassButGot,
-                 [LeftResolved.TypeEl.ElementTypeName],Bin.left);
+                 [GetElementTypeName(LeftResolved.TypeEl)],Bin.left);
       {$IFDEF VerbosePasResolver}
       {$IFDEF VerbosePasResolver}
       writeln('TPasResolver.ComputeBinaryExprRes is-operator: left=',GetResolverResultDbg(LeftResolved),' right=',GetResolverResultDbg(RightResolved));
       writeln('TPasResolver.ComputeBinaryExprRes is-operator: left=',GetResolverResultDbg(LeftResolved),' right=',GetResolverResultDbg(RightResolved));
       {$ENDIF}
       {$ENDIF}
@@ -7680,9 +7762,10 @@ begin
         if (LeftResolved.IdentEl=nil)
         if (LeftResolved.IdentEl=nil)
             or (LeftResolved.IdentEl is TPasType)
             or (LeftResolved.IdentEl is TPasType)
             or (not (rrfReadable in LeftResolved.Flags)) then
             or (not (rrfReadable in LeftResolved.Flags)) then
-          RaiseMsg(20170216152237,nIllegalQualifier,sIllegalQualifier,['as'],Bin);
+          RaiseIncompatibleTypeRes(20180204124711,nOperatorIsNotOverloadedAOpB,
+            [OpcodeStrings[Bin.OpCode]],LeftResolved,RightResolved,Bin);
         if RightResolved.IdentEl=nil then
         if RightResolved.IdentEl=nil then
-          RaiseXExpectedButYFound(20170216152630,'class',RightResolved.TypeEl.ElementTypeName,Bin.right);
+          RaiseXExpectedButYFound(20170216152630,'class',GetElementTypeName(RightResolved.TypeEl),Bin.right);
         if not (RightResolved.IdentEl is TPasType) then
         if not (RightResolved.IdentEl is TPasType) then
           RaiseXExpectedButYFound(20170216152632,'class',RightResolved.IdentEl.Name,Bin.right);
           RaiseXExpectedButYFound(20170216152632,'class',RightResolved.IdentEl.Name,Bin.right);
         if (CheckSrcIsADstType(RightResolved,LeftResolved,Bin)<>cIncompatible) then
         if (CheckSrcIsADstType(RightResolved,LeftResolved,Bin)<>cIncompatible) then
@@ -7787,7 +7870,8 @@ begin
   {$IFDEF VerbosePasResolver}
   {$IFDEF VerbosePasResolver}
   writeln('TPasResolver.ComputeBinaryExprRes OpCode=',OpcodeStrings[Bin.OpCode],' Kind=',Bin.Kind,' Left=',GetResolverResultDbg(LeftResolved),' Right=',GetResolverResultDbg(RightResolved));
   writeln('TPasResolver.ComputeBinaryExprRes OpCode=',OpcodeStrings[Bin.OpCode],' Kind=',Bin.Kind,' Left=',GetResolverResultDbg(LeftResolved),' Right=',GetResolverResultDbg(RightResolved));
   {$ENDIF}
   {$ENDIF}
-  RaiseMsg(20170216152241,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[Bin.OpCode]],Bin);
+  RaiseIncompatibleTypeRes(20180204114631,nOperatorIsNotOverloadedAOpB,
+    [OpcodeStrings[Bin.OpCode]],LeftResolved,RightResolved,Bin);
   if Flags=[] then ;
   if Flags=[] then ;
 end;
 end;
 
 
@@ -8142,7 +8226,7 @@ begin
       ['class',BaseTypeNames[ResolvedEl.BaseType]],El);
       ['class',BaseTypeNames[ResolvedEl.BaseType]],El);
   if (ResolvedEl.TypeEl.ClassType<>TPasClassType) then
   if (ResolvedEl.TypeEl.ClassType<>TPasClassType) then
     RaiseMsg(20170216152246,nXExpectedButYFound,sXExpectedButYFound,
     RaiseMsg(20170216152246,nXExpectedButYFound,sXExpectedButYFound,
-      ['class',ResolvedEl.TypeEl.ElementTypeName],El);
+      ['class',GetElementTypeName(ResolvedEl.TypeEl)],El);
 end;
 end;
 
 
 function TPasResolver.CheckTypeCastClassInstanceToClass(const FromClassRes,
 function TPasResolver.CheckTypeCastClassInstanceToClass(const FromClassRes,
@@ -8164,14 +8248,14 @@ begin
   if not (rrfReadable in LHS.Flags) then
   if not (rrfReadable in LHS.Flags) then
     begin
     begin
     if LHS.TypeEl<>nil then
     if LHS.TypeEl<>nil then
-      RaiseXExpectedButYFound(20170216152645,'ordinal',LHS.TypeEl.ElementTypeName,Left)
+      RaiseXExpectedButYFound(20170216152645,'ordinal',GetElementTypeName(LHS.TypeEl),Left)
     else
     else
       RaiseXExpectedButYFound(20170216152648,'ordinal',BaseTypeNames[LHS.BaseType],Left);
       RaiseXExpectedButYFound(20170216152648,'ordinal',BaseTypeNames[LHS.BaseType],Left);
     end;
     end;
   if not (rrfReadable in RHS.Flags) then
   if not (rrfReadable in RHS.Flags) then
     begin
     begin
     if RHS.TypeEl<>nil then
     if RHS.TypeEl<>nil then
-      RaiseXExpectedButYFound(20170216152651,'ordinal',RHS.TypeEl.ElementTypeName,Right)
+      RaiseXExpectedButYFound(20170216152651,'ordinal',GetElementTypeName(RHS.TypeEl),Right)
     else
     else
       RaiseXExpectedButYFound(20170216152653,'ordinal',BaseTypeNames[RHS.BaseType],Right);
       RaiseXExpectedButYFound(20170216152653,'ordinal',BaseTypeNames[RHS.BaseType],Right);
     end;
     end;
@@ -8203,7 +8287,7 @@ begin
       if LHS.TypeEl=RHS.TypeEl then
       if LHS.TypeEl=RHS.TypeEl then
         exit;
         exit;
       if RHS.TypeEl.ClassType<>TPasEnumType then
       if RHS.TypeEl.ClassType<>TPasEnumType then
-        RaiseXExpectedButYFound(20170216152707,LHS.TypeEl.Parent.Name,RHS.TypeEl.ElementTypeName,Right);
+        RaiseXExpectedButYFound(20170216152707,LHS.TypeEl.Parent.Name,GetElementTypeName(RHS.TypeEl),Right);
       if LHS.TypeEl.Parent<>RHS.TypeEl.Parent then
       if LHS.TypeEl.Parent<>RHS.TypeEl.Parent then
         RaiseXExpectedButYFound(20170216152710,LHS.TypeEl.Parent.Name,RHS.TypeEl.Parent.Name,Right);
         RaiseXExpectedButYFound(20170216152710,LHS.TypeEl.Parent.Name,RHS.TypeEl.Parent.Name,Right);
       end
       end
@@ -8224,7 +8308,7 @@ begin
     begin
     begin
     if ResolvedEl.TypeEl.ClassType=TPasEnumType then
     if ResolvedEl.TypeEl.ClassType=TPasEnumType then
     else if RaiseOnError then
     else if RaiseOnError then
-      RaiseXExpectedButYFound(20170216152718,'ordinal value',ResolvedEl.TypeEl.ElementTypeName,ErrorEl)
+      RaiseXExpectedButYFound(20170216152718,'ordinal value',GetElementTypeName(ResolvedEl.TypeEl),ErrorEl)
     else
     else
       exit;
       exit;
     end
     end
@@ -8519,7 +8603,7 @@ begin
       RaiseIdentifierNotFound(20171221191511,'GetEnumerator',Loop.StartExpr);
       RaiseIdentifierNotFound(20171221191511,'GetEnumerator',Loop.StartExpr);
     // check is function
     // check is function
     if Getter.Element.ClassType<>TPasFunction then
     if Getter.Element.ClassType<>TPasFunction then
-      RaiseContextXExpectedButYFound(20171221191638,'GetEnumerator','function',Getter.Element.ElementTypeName,Loop.StartExpr);
+      RaiseContextXExpectedButYFound(20171221191638,'GetEnumerator','function',GetElementTypeName(Getter.Element),Loop.StartExpr);
     GetterFunc:=TPasFunction(Getter.Element);
     GetterFunc:=TPasFunction(Getter.Element);
     // check visibility
     // check visibility
     if not (GetterFunc.Visibility in [visPublic,visPublished]) then
     if not (GetterFunc.Visibility in [visPublic,visPublished]) then
@@ -8549,7 +8633,7 @@ begin
       RaiseIdentifierNotFound(20171221195632,'MoveNext',Loop.StartExpr);
       RaiseIdentifierNotFound(20171221195632,'MoveNext',Loop.StartExpr);
     // check is function
     // check is function
     if MoveNext.Element.ClassType<>TPasFunction then
     if MoveNext.Element.ClassType<>TPasFunction then
-      RaiseContextXExpectedButYFound(20171221195651,'MoveNext','function',MoveNext.Element.ElementTypeName,Loop.StartExpr);
+      RaiseContextXExpectedButYFound(20171221195651,'MoveNext','function',GetElementTypeName(MoveNext.Element),Loop.StartExpr);
     MoveNextFunc:=TPasFunction(MoveNext.Element);
     MoveNextFunc:=TPasFunction(MoveNext.Element);
     // check visibility
     // check visibility
     if not (MoveNextFunc.Visibility in [visPublic,visPublished]) then
     if not (MoveNextFunc.Visibility in [visPublic,visPublished]) then
@@ -8572,7 +8656,7 @@ begin
       RaiseIdentifierNotFound(20171221200433,'Current',Loop.StartExpr);
       RaiseIdentifierNotFound(20171221200433,'Current',Loop.StartExpr);
     // check is property
     // check is property
     if Current.Element.ClassType<>TPasProperty then
     if Current.Element.ClassType<>TPasProperty then
-      RaiseContextXExpectedButYFound(20171221200508,'Current','property',Current.Element.ElementTypeName,Loop.StartExpr);
+      RaiseContextXExpectedButYFound(20171221200508,'Current','property',GetElementTypeName(Current.Element),Loop.StartExpr);
     CurrentProp:=TPasProperty(Current.Element);
     CurrentProp:=TPasProperty(Current.Element);
     // check visibility
     // check visibility
     if not (CurrentProp.Visibility in [visPublic,visPublished]) then
     if not (CurrentProp.Visibility in [visPublic,visPublished]) then
@@ -8723,7 +8807,7 @@ begin
   if Identifier=nil then exit;
   if Identifier=nil then exit;
   El:=Identifier.Element;
   El:=Identifier.Element;
   if not (El is TPasClassType) then
   if not (El is TPasClassType) then
-    RaiseXExpectedButYFound(20180119172517,'class '+aClassName,El.ElementTypeName,ErrorEl);
+    RaiseXExpectedButYFound(20180119172517,'class '+aClassName,GetElementTypeName(El),ErrorEl);
   aClass:=TPasClassType(El);
   aClass:=TPasClassType(El);
 
 
   ClassScope:=NoNil(aClass.CustomData) as TPasClassScope;
   ClassScope:=NoNil(aClass.CustomData) as TPasClassScope;
@@ -10781,14 +10865,14 @@ begin
     if NextEl is TPasModule then
     if NextEl is TPasModule then
       begin
       begin
       if CurScopeEl is TPasModule then
       if CurScopeEl is TPasModule then
-        RaiseXExpectedButYFound(20170328001619,'class',NextEl.ElementTypeName+' '+NextEl.Name,ErrorEl);
+        RaiseXExpectedButYFound(20170328001619,'class',GetElementTypeName(NextEl)+' '+NextEl.Name,ErrorEl);
       if Pos('.',NextEl.Name)>0 then
       if Pos('.',NextEl.Name)>0 then
         begin
         begin
         // dotted module name -> check if the full module name is in aName
         // dotted module name -> check if the full module name is in aName
         if CompareText(NextEl.Name+'.',LeftStr(aName,length(NextEl.Name)+1))<>0 then
         if CompareText(NextEl.Name+'.',LeftStr(aName,length(NextEl.Name)+1))<>0 then
           begin
           begin
           if CompareText(NextEl.Name,aName)=0 then
           if CompareText(NextEl.Name,aName)=0 then
-            RaiseXExpectedButYFound(20170504165825,'type',NextEl.ElementTypeName,ErrorEl)
+            RaiseXExpectedButYFound(20170504165825,'type',GetElementTypeName(NextEl),ErrorEl)
           else
           else
             RaiseIdentifierNotFound(20170504165412,aName,ErrorEl);
             RaiseIdentifierNotFound(20170504165412,aName,ErrorEl);
           end;
           end;
@@ -11051,7 +11135,7 @@ begin
     else
     else
       begin
       begin
       RaiseMsg(20170216152348,nCannotAccessThisMemberFromAX,
       RaiseMsg(20170216152348,nCannotAccessThisMemberFromAX,
-        sCannotAccessThisMemberFromAX,[FindData.Found.Parent.ElementTypeName],FindData.ErrorPosEl);
+        sCannotAccessThisMemberFromAX,[GetElementTypeName(FindData.Found.Parent)],FindData.ErrorPosEl);
       end;
       end;
     end
     end
   else if (proExtClassInstanceNoTypeMembers in Options)
   else if (proExtClassInstanceNoTypeMembers in Options)
@@ -11071,7 +11155,7 @@ begin
         begin
         begin
         RaiseMsg(20170331184224,nExternalClassInstanceCannotAccessStaticX,
         RaiseMsg(20170331184224,nExternalClassInstanceCannotAccessStaticX,
           sExternalClassInstanceCannotAccessStaticX,
           sExternalClassInstanceCannotAccessStaticX,
-          [FindData.Found.ElementTypeName+' '+FindData.Found.Name],
+          [GetElementTypeName(FindData.Found)+' '+FindData.Found.Name],
           FindData.ErrorPosEl);
           FindData.ErrorPosEl);
         end;
         end;
     end;
     end;
@@ -12014,6 +12098,8 @@ begin
       RaiseMsg(id,MsgNumber,sResultTypeMismatchExpectedButFound,[GotDesc,ExpDesc],ErrorEl);
       RaiseMsg(id,MsgNumber,sResultTypeMismatchExpectedButFound,[GotDesc,ExpDesc],ErrorEl);
     nXExpectedButYFound:
     nXExpectedButYFound:
       RaiseMsg(id,MsgNumber,sXExpectedButYFound,[GotDesc,ExpDesc],ErrorEl);
       RaiseMsg(id,MsgNumber,sXExpectedButYFound,[GotDesc,ExpDesc],ErrorEl);
+    nOperatorIsNotOverloadedAOpB:
+      RaiseMsg(id,MsgNumber,sOperatorIsNotOverloadedAOpB,[GotDesc,GetString(0),ExpDesc],ErrorEl);
   else
   else
     RaiseInternalError(20170329112911);
     RaiseInternalError(20170329112911);
   end;
   end;
@@ -12043,6 +12129,46 @@ begin
   {$IFDEF VerbosePasResolver}
   {$IFDEF VerbosePasResolver}
   writeln('TPasResolver.RaiseIncompatibleTypeRes Got={',GetResolverResultDbg(GotType),'} Expected={',GetResolverResultDbg(ExpType),'}');
   writeln('TPasResolver.RaiseIncompatibleTypeRes Got={',GetResolverResultDbg(GotType),'} Expected={',GetResolverResultDbg(ExpType),'}');
   {$ENDIF}
   {$ENDIF}
+  GetIncompatibleTypeDesc(GotType,ExpType,GotDesc,ExpDesc);
+  RaiseIncompatibleTypeDesc(id,MsgNumber,Args,GotDesc,ExpDesc,ErrorEl);
+end;
+
+procedure TPasResolver.RaiseInvalidProcTypeModifier(id: int64;
+  ProcType: TPasProcedureType; ptm: TProcTypeModifier; ErrorEl: TPasElement);
+begin
+  RaiseMsg(id,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(ProcType),
+    ProcTypeModifiers[ptm]],ErrorEl);
+end;
+
+procedure TPasResolver.RaiseInvalidProcModifier(id: int64; Proc: TPasProcedure;
+  pm: TProcedureModifier; ErrorEl: TPasElement);
+begin
+  RaiseMsg(id,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),
+    ModifierNames[pm]],ErrorEl);
+end;
+
+procedure TPasResolver.LogMsg(const id: int64; MsgType: TMessageType;
+  MsgNumber: integer; const Fmt: String; Args: array of const;
+  PosEl: TPasElement);
+begin
+  if (FStep<prsFinishingModule)
+      and (CurrentParser.Scanner<>nil)
+      and (CurrentParser.Scanner.IgnoreMsgType(MsgType)) then
+    exit; // during parsing consider directives like $Hints on|off
+
+  SetLastMsg(id,MsgType,MsgNumber,Fmt,Args,PosEl);
+  if Assigned(OnLog) then
+    OnLog(Self,FLastMsg)
+  else if Assigned(CurrentParser.OnLog) then
+    CurrentParser.OnLog(Self,FLastMsg);
+end;
+
+procedure TPasResolver.GetIncompatibleTypeDesc(const GotType,
+  ExpType: TPasResolverResult; out GotDesc, ExpDesc: String);
+begin
+  {$IFDEF VerbosePasResolver}
+  writeln('TPasResolver.GetIncompatibleTypeDesc Got={',GetResolverResultDbg(GotType),'} Expected={',GetResolverResultDbg(ExpType),'}');
+  {$ENDIF}
   if GotType.BaseType<>ExpType.BaseType then
   if GotType.BaseType<>ExpType.BaseType then
     begin
     begin
     GotDesc:=GetBaseDescription(GotType);
     GotDesc:=GetBaseDescription(GotType);
@@ -12060,6 +12186,7 @@ begin
     begin
     begin
     GotDesc:=GetTypeDescription(GotType);
     GotDesc:=GetTypeDescription(GotType);
     ExpDesc:=GetTypeDescription(ExpType);
     ExpDesc:=GetTypeDescription(ExpType);
+    writeln('AAA1 TPasResolver.GetIncompatibleTypeDesc {',ExpDesc,'}');
     if GotDesc=ExpDesc then
     if GotDesc=ExpDesc then
       begin
       begin
       GotDesc:=GetTypeDescription(GotType,true);
       GotDesc:=GetTypeDescription(GotType,true);
@@ -12076,37 +12203,6 @@ begin
       ExpDesc:=GetResolverResultDescription(ExpType,false);
       ExpDesc:=GetResolverResultDescription(ExpType,false);
       end;
       end;
     end;
     end;
-  RaiseIncompatibleTypeDesc(id,MsgNumber,Args,GotDesc,ExpDesc,ErrorEl);
-end;
-
-procedure TPasResolver.RaiseInvalidProcTypeModifier(id: int64;
-  ProcType: TPasProcedureType; ptm: TProcTypeModifier; ErrorEl: TPasElement);
-begin
-  RaiseMsg(id,nInvalidXModifierY,sInvalidXModifierY,[ProcType.ElementTypeName,
-    ProcTypeModifiers[ptm]],ErrorEl);
-end;
-
-procedure TPasResolver.RaiseInvalidProcModifier(id: int64; Proc: TPasProcedure;
-  pm: TProcedureModifier; ErrorEl: TPasElement);
-begin
-  RaiseMsg(id,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,
-    ModifierNames[pm]],ErrorEl);
-end;
-
-procedure TPasResolver.LogMsg(const id: int64; MsgType: TMessageType;
-  MsgNumber: integer; const Fmt: String; Args: array of const;
-  PosEl: TPasElement);
-begin
-  if (FStep<prsFinishingModule)
-      and (CurrentParser.Scanner<>nil)
-      and (CurrentParser.Scanner.IgnoreMsgType(MsgType)) then
-    exit; // during parsing consider directives like $Hints on|off
-
-  SetLastMsg(id,MsgType,MsgNumber,Fmt,Args,PosEl);
-  if Assigned(OnLog) then
-    OnLog(Self,FLastMsg)
-  else if Assigned(CurrentParser.OnLog) then
-    CurrentParser.OnLog(Self,FLastMsg);
 end;
 end;
 
 
 function TPasResolver.CheckCallProcCompatibility(ProcType: TPasProcedureType;
 function TPasResolver.CheckCallProcCompatibility(ProcType: TPasProcedureType;
@@ -12382,7 +12478,7 @@ function TPasResolver.CheckProcTypeCompatibility(Proc1,
     Result:=false;
     Result:=false;
     if not RaiseOnIncompatible then exit;
     if not RaiseOnIncompatible then exit;
     RaiseMsg(20170402112049,nXModifierMismatchY,sXModifierMismatchY,
     RaiseMsg(20170402112049,nXModifierMismatchY,sXModifierMismatchY,
-      [Proc1.ElementTypeName,ProcTypeModifiers[Modifier]],ErrorEl);
+      [GetElementTypeName(Proc1),ProcTypeModifiers[Modifier]],ErrorEl);
   end;
   end;
 
 
 var
 var
@@ -12395,7 +12491,7 @@ begin
   if Proc1.ClassType<>Proc2.ClassType then
   if Proc1.ClassType<>Proc2.ClassType then
     begin
     begin
     if RaiseOnIncompatible then
     if RaiseOnIncompatible then
-      RaiseXExpectedButYFound(20170402112353,Proc1.ElementTypeName,Proc2.ElementTypeName,ErrorEl);
+      RaiseXExpectedButYFound(20170402112353,GetElementTypeName(Proc1),GetElementTypeName(Proc2),ErrorEl);
     exit;
     exit;
     end;
     end;
   if Proc1.IsReferenceTo then
   if Proc1.IsReferenceTo then
@@ -12549,7 +12645,7 @@ begin
       writeln('TPasResolver.CheckCanBeLHS ',GetResolverResultDbg(ResolvedEl));
       writeln('TPasResolver.CheckCanBeLHS ',GetResolverResultDbg(ResolvedEl));
       {$ENDIF}
       {$ENDIF}
       if (ResolvedEl.TypeEl<>nil) and (ResolvedEl.ExprEl<>nil) then
       if (ResolvedEl.TypeEl<>nil) and (ResolvedEl.ExprEl<>nil) then
-        RaiseXExpectedButYFound(20170216152727,'identifier',ResolvedEl.TypeEl.ElementTypeName,ResolvedEl.ExprEl)
+        RaiseXExpectedButYFound(20170216152727,'identifier',GetElementTypeName(ResolvedEl.TypeEl),ResolvedEl.ExprEl)
       else
       else
         RaiseMsg(20170216152426,nVariableIdentifierExpected,sVariableIdentifierExpected,[],ErrorEl);
         RaiseMsg(20170216152426,nVariableIdentifierExpected,sVariableIdentifierExpected,[],ErrorEl);
       end;
       end;
@@ -13589,7 +13685,7 @@ var
   ArrayEl: TPasArrayType;
   ArrayEl: TPasArrayType;
 begin
 begin
   case T.BaseType of
   case T.BaseType of
-  btModule: exit(T.IdentEl.ElementTypeName+' '+T.IdentEl.Name);
+  btModule: exit(GetElementTypeName(T.IdentEl)+' '+T.IdentEl.Name);
   btNil: exit('nil');
   btNil: exit('nil');
   btRange:
   btRange:
     Result:='range of '+GetSubTypeName;
     Result:='range of '+GetSubTypeName;
@@ -13662,10 +13758,10 @@ function TPasResolver.GetTypeDescription(const R: TPasResolverResult;
   AddPath: boolean): string;
   AddPath: boolean): string;
 begin
 begin
   Result:=GetTypeDescription(R.TypeEl,AddPath);
   Result:=GetTypeDescription(R.TypeEl,AddPath);
-  if R.IdentEl=R.TypeEl then
+  if (R.TypeEl<>nil) and (R.IdentEl=R.TypeEl) then
     begin
     begin
     if R.TypeEl.ElementTypeName<>'' then
     if R.TypeEl.ElementTypeName<>'' then
-      Result:=R.TypeEl.ElementTypeName+' '+Result
+      Result:=GetElementTypeName(R.TypeEl)+' '+Result
     else
     else
       Result:='type '+Result;
       Result:='type '+Result;
     end;
     end;
@@ -13938,7 +14034,7 @@ begin
       begin
       begin
       if (RTypeEl is TPasProcedureType) and (rrfReadable in RHS.Flags) then
       if (RTypeEl is TPasProcedureType) and (rrfReadable in RHS.Flags) then
         RaiseMsg(20170404154738,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
         RaiseMsg(20170404154738,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
-          [RTypeEl.ElementTypeName,LTypeEl.ElementTypeName],ErrorEl);
+          [GetElementTypeName(RTypeEl),GetElementTypeName(LTypeEl)],ErrorEl);
       end;
       end;
     end
     end
   else if LTypeEl.ClassType=TPasArrayType then
   else if LTypeEl.ClassType=TPasArrayType then
@@ -14536,14 +14632,14 @@ begin
                   Result:=cCompatible
                   Result:=cCompatible
                 else if RaiseOnError then
                 else if RaiseOnError then
                   RaiseMsg(20170416183615,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
                   RaiseMsg(20170416183615,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
-                    [FromProcType.ElementTypeName+' '+ProcTypeModifiers[ptmOfObject],
+                    [GetElementTypeName(FromProcType)+' '+ProcTypeModifiers[ptmOfObject],
                      BaseTypeNames[btPointer]],ErrorEl);
                      BaseTypeNames[btPointer]],ErrorEl);
                 end
                 end
               else if FromProcType.IsNested then
               else if FromProcType.IsNested then
                 begin
                 begin
                 if RaiseOnError then
                 if RaiseOnError then
                   RaiseMsg(20170416183800,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
                   RaiseMsg(20170416183800,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
-                    [FromProcType.ElementTypeName+' '+ProcTypeModifiers[ptmIsNested],
+                    [GetElementTypeName(FromProcType)+' '+ProcTypeModifiers[ptmIsNested],
                      BaseTypeNames[btPointer]],ErrorEl);
                      BaseTypeNames[btPointer]],ErrorEl);
                 end
                 end
               else if FromProcType.IsReferenceTo then
               else if FromProcType.IsReferenceTo then
@@ -14552,7 +14648,7 @@ begin
                   Result:=cCompatible
                   Result:=cCompatible
                 else if RaiseOnError then
                 else if RaiseOnError then
                   RaiseMsg(20170419144311,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
                   RaiseMsg(20170419144311,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
-                    [FromProcType.ElementTypeName+' '+ProcTypeModifiers[ptmReferenceTo],
+                    [GetElementTypeName(FromProcType)+' '+ProcTypeModifiers[ptmReferenceTo],
                      BaseTypeNames[btPointer]],ErrorEl);
                      BaseTypeNames[btPointer]],ErrorEl);
                 end
                 end
               else
               else
@@ -14687,14 +14783,14 @@ begin
             begin
             begin
             if RaiseOnError then
             if RaiseOnError then
               RaiseMsg(20170416183109,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
               RaiseMsg(20170416183109,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
-                [FromProcType.ElementTypeName+BoolToStr(FromProcType.IsOfObject,' '+ProcTypeModifiers[ptmOfObject],''),
+                [GetElementTypeName(FromProcType)+BoolToStr(FromProcType.IsOfObject,' '+ProcTypeModifiers[ptmOfObject],''),
                  ToProcType.ElementTypeName+BoolToStr(ToProcType.IsOfObject,' '+ProcTypeModifiers[ptmOfObject],'')],ErrorEl);
                  ToProcType.ElementTypeName+BoolToStr(ToProcType.IsOfObject,' '+ProcTypeModifiers[ptmOfObject],'')],ErrorEl);
             end
             end
           else if FromProcType.IsNested<>ToProcType.IsNested then
           else if FromProcType.IsNested<>ToProcType.IsNested then
             begin
             begin
             if RaiseOnError then
             if RaiseOnError then
               RaiseMsg(20170416183305,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
               RaiseMsg(20170416183305,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
-                [FromProcType.ElementTypeName+BoolToStr(FromProcType.IsNested,' '+ProcTypeModifiers[ptmIsNested],''),
+                [GetElementTypeName(FromProcType)+BoolToStr(FromProcType.IsNested,' '+ProcTypeModifiers[ptmIsNested],''),
                  ToProcType.ElementTypeName+BoolToStr(ToProcType.IsNested,' '+ProcTypeModifiers[ptmIsNested],'')],ErrorEl);
                  ToProcType.ElementTypeName+BoolToStr(ToProcType.IsNested,' '+ProcTypeModifiers[ptmIsNested],'')],ErrorEl);
             end
             end
           else
           else

+ 2 - 2
packages/fcl-passrc/src/pastree.pp

@@ -519,7 +519,7 @@ type
     Params: TFPList; // list of TPasType or TPasExpr
     Params: TFPList; // list of TPasType or TPasExpr
   end;
   end;
 
 
-  { TInlineTypeExpr }
+  { TInlineTypeExpr - not used by TPasParser}
 
 
   TInlineTypeExpr = class(TPasExpr)
   TInlineTypeExpr = class(TPasExpr)
   public
   public
@@ -532,7 +532,7 @@ type
     DestType: TPasType;
     DestType: TPasType;
   end;
   end;
 
 
-  { TInlineSpecializeExpr }
+  { TInlineSpecializeExpr - A<B,C> }
 
 
   TInlineSpecializeExpr = class(TInlineTypeExpr)
   TInlineSpecializeExpr = class(TInlineTypeExpr)
   end;
   end;

+ 25 - 11
packages/fcl-passrc/tests/tcresolver.pas

@@ -277,6 +277,7 @@ type
     Procedure TestAssignIntToStringFail;
     Procedure TestAssignIntToStringFail;
     Procedure TestAssignStringToIntFail;
     Procedure TestAssignStringToIntFail;
     Procedure TestIntegerOperators;
     Procedure TestIntegerOperators;
+    Procedure TestIntegerBoolFail;
     Procedure TestBooleanOperators;
     Procedure TestBooleanOperators;
     Procedure TestStringOperators;
     Procedure TestStringOperators;
     Procedure TestWideCharOperators;
     Procedure TestWideCharOperators;
@@ -3770,6 +3771,17 @@ begin
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
+procedure TTestResolver.TestIntegerBoolFail;
+begin
+  StartProgram(false);
+  Add([
+  'var i: longint;',
+  'begin',
+  '  i:=3 * false;']);
+  CheckResolverException('Operator is not overloaded: "Longint" * "Boolean"',
+    nOperatorIsNotOverloadedAOpB);
+end;
+
 procedure TTestResolver.TestBooleanOperators;
 procedure TTestResolver.TestBooleanOperators;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -8603,7 +8615,7 @@ begin
   Add('var cars: TCars;');
   Add('var cars: TCars;');
   Add('begin');
   Add('begin');
   Add('  if cars is TCars then ;');
   Add('  if cars is TCars then ;');
-  CheckResolverException('left side of is-operator expects a class, but got "class of" type',
+  CheckResolverException('left side of is-operator expects a class, but got "class of"',
     nLeftSideOfIsOperatorExpectsAClassButGot);
     nLeftSideOfIsOperatorExpectsAClassButGot);
 end;
 end;
 
 
@@ -8619,7 +8631,8 @@ begin
   Add('  cars: TCars;');
   Add('  cars: TCars;');
   Add('begin');
   Add('begin');
   Add('  cars:=cars as TCars;');
   Add('  cars:=cars as TCars;');
-  CheckResolverException('illegal qualifier "as"',nIllegalQualifier);
+  CheckResolverException('Operator is not overloaded: "TCars" as "class of TCars"',
+    nOperatorIsNotOverloadedAOpB);
 end;
 end;
 
 
 procedure TTestResolver.TestClassOfIsOperator;
 procedure TTestResolver.TestClassOfIsOperator;
@@ -8935,7 +8948,8 @@ begin
   Add('  c: tclass;');
   Add('  c: tclass;');
   Add('begin');
   Add('begin');
   Add('  c:=c as TClass;');
   Add('  c:=c as TClass;');
-  CheckResolverException('illegal qualifier "as"',nIllegalQualifier);
+  CheckResolverException('Operator is not overloaded: "TClass" as "class of TClass"',
+    nOperatorIsNotOverloadedAOpB);
 end;
 end;
 
 
 procedure TTestResolver.TestClassOf_MemberAsFail;
 procedure TTestResolver.TestClassOf_MemberAsFail;
@@ -8949,7 +8963,7 @@ begin
   Add('var o: TObject;');
   Add('var o: TObject;');
   Add('begin');
   Add('begin');
   Add('  o.c:=o.c as TClass;');
   Add('  o.c:=o.c as TClass;');
-  CheckResolverException('illegal qualifier "as"',nIllegalQualifier);
+  CheckResolverException('Operator is not overloaded: "TClass" as "class of TClass"',nOperatorIsNotOverloadedAOpB);
 end;
 end;
 
 
 procedure TTestResolver.TestClassOf_IsFail;
 procedure TTestResolver.TestClassOf_IsFail;
@@ -8963,7 +8977,7 @@ begin
   Add('  c: tclass;');
   Add('  c: tclass;');
   Add('begin');
   Add('begin');
   Add('  if c is TObject then;');
   Add('  if c is TObject then;');
-  CheckResolverException('left side of is-operator expects a class, but got "class of" type',
+  CheckResolverException('left side of is-operator expects a class, but got "class of"',
     nLeftSideOfIsOperatorExpectsAClassButGot);
     nLeftSideOfIsOperatorExpectsAClassButGot);
 end;
 end;
 
 
@@ -11005,7 +11019,7 @@ begin
   Add('var n: TNotifyEvent;');
   Add('var n: TNotifyEvent;');
   Add('begin');
   Add('begin');
   Add('  n:=@ProcA;');
   Add('  n:=@ProcA;');
-  CheckResolverException('procedure type modifier "of Object" mismatch',
+  CheckResolverException('procedural type modifier "of Object" mismatch',
     nXModifierMismatchY);
     nXModifierMismatchY);
 end;
 end;
 
 
@@ -11024,7 +11038,7 @@ begin
   Add('  o: TObject;');
   Add('  o: TObject;');
   Add('begin');
   Add('begin');
   Add('  n:[email protected];');
   Add('  n:[email protected];');
-  CheckResolverException('procedure type modifier "of Object" mismatch',
+  CheckResolverException('procedural type modifier "of Object" mismatch',
     nXModifierMismatchY);
     nXModifierMismatchY);
 end;
 end;
 
 
@@ -11039,7 +11053,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  p:=@ProcA;');
   Add('  p:=@ProcA;');
   CheckResolverException(
   CheckResolverException(
-    'Incompatible types: got "procedure type" expected "function type"',
+    'Incompatible types: got "procedural type" expected "functional type"',
     nIncompatibleTypesGotExpected);
     nIncompatibleTypesGotExpected);
 end;
 end;
 
 
@@ -11085,7 +11099,7 @@ begin
   Add('  p:=@SubProc;');
   Add('  p:=@SubProc;');
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('procedure type modifier "is nested" mismatch',
+  CheckResolverException('procedural type modifier "is nested" mismatch',
     nXModifierMismatchY);
     nXModifierMismatchY);
 end;
 end;
 
 
@@ -11284,7 +11298,7 @@ begin
   Add('var p: TNestedProc;');
   Add('var p: TNestedProc;');
   Add('begin');
   Add('begin');
   Add('  p:=@DoIt;');
   Add('  p:=@DoIt;');
-  CheckResolverException('procedure type modifier "is nested" mismatch',nXModifierMismatchY);
+  CheckResolverException('procedural type modifier "is nested" mismatch',nXModifierMismatchY);
 end;
 end;
 
 
 procedure TTestResolver.TestProcType_ReferenceTo;
 procedure TTestResolver.TestProcType_ReferenceTo;
@@ -11656,7 +11670,7 @@ begin
   Add('  e: TEvent;');
   Add('  e: TEvent;');
   Add('begin');
   Add('begin');
   Add('  p:=Pointer(e);');
   Add('  p:=Pointer(e);');
-  CheckResolverException('Illegal type conversion: "procedure type of Object" to "Pointer"',
+  CheckResolverException('Illegal type conversion: "procedural type of Object" to "Pointer"',
     nIllegalTypeConversionTo);
     nIllegalTypeConversionTo);
 end;
 end;