Browse Source

fcl-passrc: resolver: check duplicates in set const

git-svn-id: trunk@36731 -
Mattias Gaertner 8 years ago
parent
commit
a29c7c7fac

+ 128 - 61
packages/fcl-passrc/src/pasresolveeval.pas

@@ -44,10 +44,9 @@ Works:
 - set of enum, set of char, set of bool, set of int
 - set of enum, set of char, set of bool, set of int
   - [a,b,c..d]
   - [a,b,c..d]
   - +, -, *, ><, =, <>, >=, <=, in
   - +, -, *, ><, =, <>, >=, <=, in
+  - error on duplicate in const set
 
 
 ToDo:
 ToDo:
-- sets
-  - error on duplicate
 - arrays
 - arrays
   - length(), low(), high(), []
   - length(), low(), high(), []
 }
 }
@@ -134,6 +133,7 @@ const
   nIllegalChar = 3067;
   nIllegalChar = 3067;
   nOverflowInArithmeticOperation = 3068;
   nOverflowInArithmeticOperation = 3068;
   nDivByZero = 3069;
   nDivByZero = 3069;
+  nRangeCheckInSetConstructor = 3070;
 
 
 // resourcestring patterns of messages
 // resourcestring patterns of messages
 resourcestring
 resourcestring
@@ -206,6 +206,7 @@ resourcestring
   sIllegalChar = 'Illegal character';
   sIllegalChar = 'Illegal character';
   sOverflowInArithmeticOperation = 'Overflow in arithmetic operation';
   sOverflowInArithmeticOperation = 'Overflow in arithmetic operation';
   sDivByZero = 'Division by zero';
   sDivByZero = 'Division by zero';
+  sRangeCheckInSetConstructor = 'range check error in set constructor or duplicate set element';
 
 
 type
 type
   { TResolveData - base class for data stored in TPasElement.CustomData }
   { TResolveData - base class for data stored in TPasElement.CustomData }
@@ -405,9 +406,9 @@ type
     function AsString: string; override;
     function AsString: string; override;
   end;
   end;
 
 
-  { TResEvalSetInt - Kind=revkSetOfInt }
+  { TResEvalSet - Kind=revkSetOfInt }
 
 
-  TResEvalSetInt = class(TResEvalValue)
+  TResEvalSet = class(TResEvalValue)
   public
   public
     const MaxCount = $ffff;
     const MaxCount = $ffff;
     type
     type
@@ -419,12 +420,13 @@ type
     ElKind: TRESetElKind;
     ElKind: TRESetElKind;
     Ranges: TItems; // disjunct, sorted ascending
     Ranges: TItems; // disjunct, sorted ascending
     constructor Create; override;
     constructor Create; override;
-    constructor CreateEmpty(aSet: TResEvalSetInt);
+    constructor CreateEmpty(aSet: TResEvalSet);
     function Clone: TResEvalValue; override;
     function Clone: TResEvalValue; override;
     function AsString: string; override;
     function AsString: string; override;
     function ElementAsString(El: MaxPrecInt): string;
     function ElementAsString(El: MaxPrecInt): string;
     function Add(RangeStart, RangeEnd: MaxPrecInt): boolean; // false if duplicate ignored
     function Add(RangeStart, RangeEnd: MaxPrecInt): boolean; // false if duplicate ignored
     function IndexOfRange(Index: MaxPrecInt; FindInsertPos: boolean = false): integer;
     function IndexOfRange(Index: MaxPrecInt; FindInsertPos: boolean = false): integer;
+    function Intersects(RangeStart, RangeEnd: MaxPrecInt): integer; // returns index of first intersecting range
     procedure ConsistencyCheck;
     procedure ConsistencyCheck;
   end;
   end;
 
 
@@ -482,7 +484,7 @@ type
     function EvalBinarySymmetricaldifferenceExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
     function EvalBinarySymmetricaldifferenceExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
     function EvalParamsExpr(Expr: TParamsExpr; Flags: TResEvalFlags): TResEvalValue;
     function EvalParamsExpr(Expr: TParamsExpr; Flags: TResEvalFlags): TResEvalValue;
     function EvalArrayParamsExpr(Expr: TParamsExpr; Flags: TResEvalFlags): TResEvalValue;
     function EvalArrayParamsExpr(Expr: TParamsExpr; Flags: TResEvalFlags): TResEvalValue;
-    function EvalSetParamsExpr(Expr: TParamsExpr; Flags: TResEvalFlags): TResEvalSetInt;
+    function EvalSetParamsExpr(Expr: TParamsExpr; Flags: TResEvalFlags): TResEvalSet;
     function ExprStringToOrd(Value: TResEvalValue; PosEl: TPasElement): longword; virtual;
     function ExprStringToOrd(Value: TResEvalValue; PosEl: TPasElement): longword; virtual;
     function EvalPrimitiveExprString(Expr: TPrimitiveExpr): TResEvalValue; virtual;
     function EvalPrimitiveExprString(Expr: TPrimitiveExpr): TResEvalValue; virtual;
     procedure PredBool(Value: TResEvalBool; ErrorEl: TPasElement);
     procedure PredBool(Value: TResEvalBool; ErrorEl: TPasElement);
@@ -1205,7 +1207,7 @@ var
   UInt: MaxPrecUInt;
   UInt: MaxPrecUInt;
   Flo: MaxPrecFloat;
   Flo: MaxPrecFloat;
   LeftCP, RightCP: TSystemCodePage;
   LeftCP, RightCP: TSystemCodePage;
-  LeftSet, RightSet: TResEvalSetInt;
+  LeftSet, RightSet: TResEvalSet;
   i: Integer;
   i: Integer;
 begin
 begin
   Result:=nil;
   Result:=nil;
@@ -1330,8 +1332,8 @@ begin
       revkSetOfInt:
       revkSetOfInt:
         begin
         begin
         // union
         // union
-        LeftSet:=TResEvalSetInt(LeftValue);
-        RightSet:=TResEvalSetInt(RightValue);
+        LeftSet:=TResEvalSet(LeftValue);
+        RightSet:=TResEvalSet(RightValue);
         if LeftSet.ElKind=revskNone then
         if LeftSet.ElKind=revskNone then
           Result:=RightSet.Clone
           Result:=RightSet.Clone
         else if RightSet.ElKind=revskNone then
         else if RightSet.ElKind=revskNone then
@@ -1341,8 +1343,14 @@ begin
           Result:=RightSet.Clone;
           Result:=RightSet.Clone;
           // add elements of left
           // add elements of left
           for i:=0 to length(LeftSet.Ranges)-1 do
           for i:=0 to length(LeftSet.Ranges)-1 do
-            for Int:=LeftSet.Ranges[i].RangeStart to LeftSet.Ranges[i].RangeEnd do
-              TResEvalSetInt(Result).Add(Int,Int);
+            begin
+            Int:=LeftSet.Ranges[i].RangeStart;
+            while Int<=LeftSet.Ranges[i].RangeEnd do
+              begin
+              TResEvalSet(Result).Add(Int,Int);
+              inc(Int);
+              end;
+            end;
           end;
           end;
         end;
         end;
       else
       else
@@ -1371,7 +1379,7 @@ var
   Int: MaxPrecInt;
   Int: MaxPrecInt;
   UInt: MaxPrecUInt;
   UInt: MaxPrecUInt;
   Flo: MaxPrecFloat;
   Flo: MaxPrecFloat;
-  LeftSet, RightSet: TResEvalSetInt;
+  LeftSet, RightSet: TResEvalSet;
   i: Integer;
   i: Integer;
 begin
 begin
   Result:=nil;
   Result:=nil;
@@ -1519,18 +1527,24 @@ begin
     revkSetOfInt:
     revkSetOfInt:
       begin
       begin
       // difference
       // difference
-      LeftSet:=TResEvalSetInt(LeftValue);
-      RightSet:=TResEvalSetInt(RightValue);
+      LeftSet:=TResEvalSet(LeftValue);
+      RightSet:=TResEvalSet(RightValue);
       if LeftSet.ElKind=revskNone then
       if LeftSet.ElKind=revskNone then
-        Result:=TResEvalSetInt.CreateEmpty(RightSet)
+        Result:=TResEvalSet.CreateEmpty(RightSet)
       else
       else
         begin
         begin
-        Result:=TResEvalSetInt.CreateEmpty(LeftSet);
+        Result:=TResEvalSet.CreateEmpty(LeftSet);
         // add elements, which exists only in LeftSet
         // add elements, which exists only in LeftSet
         for i:=0 to length(LeftSet.Ranges)-1 do
         for i:=0 to length(LeftSet.Ranges)-1 do
-          for Int:=LeftSet.Ranges[i].RangeStart to LeftSet.Ranges[i].RangeEnd do
+          begin
+          Int:=LeftSet.Ranges[i].RangeStart;
+          while Int<=LeftSet.Ranges[i].RangeEnd do
+            begin
             if RightSet.IndexOfRange(Int)<0 then
             if RightSet.IndexOfRange(Int)<0 then
-              TResEvalSetInt(Result).Add(Int,Int);
+              TResEvalSet(Result).Add(Int,Int);
+            inc(Int);
+            end;
+          end;
         end;
         end;
       end;
       end;
     else
     else
@@ -1553,7 +1567,7 @@ var
   Int: MaxPrecInt;
   Int: MaxPrecInt;
   UInt: MaxPrecUInt;
   UInt: MaxPrecUInt;
   Flo: MaxPrecFloat;
   Flo: MaxPrecFloat;
-  LeftSet, RightSet: TResEvalSetInt;
+  LeftSet, RightSet: TResEvalSet;
   i: Integer;
   i: Integer;
 begin
 begin
   Result:=nil;
   Result:=nil;
@@ -1712,18 +1726,24 @@ begin
     revkSetOfInt:
     revkSetOfInt:
       begin
       begin
       // intersect
       // intersect
-      LeftSet:=TResEvalSetInt(LeftValue);
-      RightSet:=TResEvalSetInt(RightValue);
+      LeftSet:=TResEvalSet(LeftValue);
+      RightSet:=TResEvalSet(RightValue);
       if LeftSet.ElKind=revskNone then
       if LeftSet.ElKind=revskNone then
-        Result:=TResEvalSetInt.CreateEmpty(RightSet)
+        Result:=TResEvalSet.CreateEmpty(RightSet)
       else
       else
         begin
         begin
-        Result:=TResEvalSetInt.CreateEmpty(LeftSet);
+        Result:=TResEvalSet.CreateEmpty(LeftSet);
         // add elements, which exists in both
         // add elements, which exists in both
         for i:=0 to length(LeftSet.Ranges)-1 do
         for i:=0 to length(LeftSet.Ranges)-1 do
-          for Int:=LeftSet.Ranges[i].RangeStart to LeftSet.Ranges[i].RangeEnd do
+          begin
+          Int:=LeftSet.Ranges[i].RangeStart;
+          while Int<=LeftSet.Ranges[i].RangeEnd do
+            begin
             if RightSet.IndexOfRange(Int)>=0 then
             if RightSet.IndexOfRange(Int)>=0 then
-              TResEvalSetInt(Result).Add(Int,Int);
+              TResEvalSet(Result).Add(Int,Int);
+            inc(Int);
+            end;
+          end;
         end;
         end;
       end;
       end;
     else
     else
@@ -2162,7 +2182,7 @@ function TResExprEvaluator.EvalBinaryNEqualExpr(Expr: TBinaryExpr; LeftValue,
   RightValue: TResEvalValue): TResEvalValue;
   RightValue: TResEvalValue): TResEvalValue;
 var
 var
   UInt: MaxPrecUInt;
   UInt: MaxPrecUInt;
-  LeftSet, RightSet: TResEvalSetInt;
+  LeftSet, RightSet: TResEvalSet;
   i: Integer;
   i: Integer;
 begin
 begin
   Result:=TResEvalBool.Create;
   Result:=TResEvalBool.Create;
@@ -2267,8 +2287,8 @@ begin
       case RightValue.Kind of
       case RightValue.Kind of
       revkSetOfInt:
       revkSetOfInt:
         begin
         begin
-        LeftSet:=TResEvalSetInt(LeftValue);
-        RightSet:=TResEvalSetInt(RightValue);
+        LeftSet:=TResEvalSet(LeftValue);
+        RightSet:=TResEvalSet(RightValue);
         if LeftSet.ElKind=revskNone then
         if LeftSet.ElKind=revskNone then
           TResEvalBool(Result).B:=length(RightSet.Ranges)=0
           TResEvalBool(Result).B:=length(RightSet.Ranges)=0
         else if RightSet.ElKind=revskNone then
         else if RightSet.ElKind=revskNone then
@@ -2330,7 +2350,7 @@ function TResExprEvaluator.EvalBinaryLessGreaterExpr(Expr: TBinaryExpr;
   end;
   end;
 
 
 var
 var
-  LeftSet, RightSet: TResEvalSetInt;
+  LeftSet, RightSet: TResEvalSet;
   i: Integer;
   i: Integer;
   Int: MaxPrecInt;
   Int: MaxPrecInt;
 begin
 begin
@@ -2510,32 +2530,44 @@ begin
       case RightValue.Kind of
       case RightValue.Kind of
       revkSetOfInt:
       revkSetOfInt:
         begin
         begin
-        LeftSet:=TResEvalSetInt(LeftValue);
-        RightSet:=TResEvalSetInt(RightValue);
+        LeftSet:=TResEvalSet(LeftValue);
+        RightSet:=TResEvalSet(RightValue);
         case Expr.OpCode of
         case Expr.OpCode of
         eopGreaterThanEqual:
         eopGreaterThanEqual:
           begin
           begin
           // >=  ->  true if all elements of RightSet are in LeftSet
           // >=  ->  true if all elements of RightSet are in LeftSet
           TResEvalBool(Result).B:=true;
           TResEvalBool(Result).B:=true;
           for i:=0 to length(RightSet.Ranges)-1 do
           for i:=0 to length(RightSet.Ranges)-1 do
-            for Int:=RightSet.Ranges[i].RangeStart to RightSet.Ranges[i].RangeEnd do
+            begin
+            Int:=RightSet.Ranges[i].RangeStart;
+            while Int<=RightSet.Ranges[i].RangeEnd do
+              begin
               if LeftSet.IndexOfRange(Int)<0 then
               if LeftSet.IndexOfRange(Int)<0 then
                 begin
                 begin
                 TResEvalBool(Result).B:=false;
                 TResEvalBool(Result).B:=false;
                 break;
                 break;
                 end;
                 end;
+              inc(Int);
+              end;
+            end;
           end;
           end;
         eopLessthanEqual:
         eopLessthanEqual:
           begin
           begin
           // <=  ->  true if all elements of LeftSet are in RightSet
           // <=  ->  true if all elements of LeftSet are in RightSet
           TResEvalBool(Result).B:=true;
           TResEvalBool(Result).B:=true;
           for i:=0 to length(LeftSet.Ranges)-1 do
           for i:=0 to length(LeftSet.Ranges)-1 do
-            for Int:=LeftSet.Ranges[i].RangeStart to LeftSet.Ranges[i].RangeEnd do
+            begin
+            Int:=LeftSet.Ranges[i].RangeStart;
+            while Int<=LeftSet.Ranges[i].RangeEnd do
+              begin
               if RightSet.IndexOfRange(Int)<0 then
               if RightSet.IndexOfRange(Int)<0 then
                 begin
                 begin
                 TResEvalBool(Result).B:=false;
                 TResEvalBool(Result).B:=false;
                 break;
                 break;
                 end;
                 end;
+              inc(Int);
+              end;
+            end;
           end
           end
         else
         else
           {$IFDEF VerbosePasResolver}
           {$IFDEF VerbosePasResolver}
@@ -2570,14 +2602,14 @@ end;
 function TResExprEvaluator.EvalBinaryInExpr(Expr: TBinaryExpr; LeftValue,
 function TResExprEvaluator.EvalBinaryInExpr(Expr: TBinaryExpr; LeftValue,
   RightValue: TResEvalValue): TResEvalValue;
   RightValue: TResEvalValue): TResEvalValue;
 var
 var
-  RightSet: TResEvalSetInt;
+  RightSet: TResEvalSet;
   Int: MaxPrecInt;
   Int: MaxPrecInt;
 begin
 begin
   Result:=nil;
   Result:=nil;
   case RightValue.Kind of
   case RightValue.Kind of
   revkSetOfInt:
   revkSetOfInt:
     begin
     begin
-    RightSet:=TResEvalSetInt(RightValue);
+    RightSet:=TResEvalSet(RightValue);
     case LeftValue.Kind of
     case LeftValue.Kind of
     revkBool:
     revkBool:
       Int:=ord(TResEvalBool(LeftValue).B);
       Int:=ord(TResEvalBool(LeftValue).B);
@@ -2622,7 +2654,7 @@ end;
 function TResExprEvaluator.EvalBinarySymmetricaldifferenceExpr(
 function TResExprEvaluator.EvalBinarySymmetricaldifferenceExpr(
   Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
   Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
 var
 var
-  LeftSet, RightSet: TResEvalSetInt;
+  LeftSet, RightSet: TResEvalSet;
   i: Integer;
   i: Integer;
   Int: MaxPrecInt;
   Int: MaxPrecInt;
 begin
 begin
@@ -2632,22 +2664,34 @@ begin
     revkSetOfInt:
     revkSetOfInt:
       begin
       begin
       // sym diff
       // sym diff
-      LeftSet:=TResEvalSetInt(LeftValue);
-      RightSet:=TResEvalSetInt(RightValue);
+      LeftSet:=TResEvalSet(LeftValue);
+      RightSet:=TResEvalSet(RightValue);
       // elements, which exists in either, but not both
       // elements, which exists in either, but not both
       if LeftSet.ElKind=revskNone then
       if LeftSet.ElKind=revskNone then
         Result:=RightSet.Clone
         Result:=RightSet.Clone
       else
       else
         begin
         begin
-        Result:=TResEvalSetInt.CreateEmpty(LeftSet);
+        Result:=TResEvalSet.CreateEmpty(LeftSet);
         for i:=0 to length(LeftSet.Ranges)-1 do
         for i:=0 to length(LeftSet.Ranges)-1 do
-          for Int:=LeftSet.Ranges[i].RangeStart to LeftSet.Ranges[i].RangeEnd do
+          begin
+          Int:=LeftSet.Ranges[i].RangeStart;
+          while Int<=LeftSet.Ranges[i].RangeEnd do
+            begin
             if RightSet.IndexOfRange(Int)<0 then
             if RightSet.IndexOfRange(Int)<0 then
-              TResEvalSetInt(Result).Add(Int,Int);
+              TResEvalSet(Result).Add(Int,Int);
+            inc(Int);
+            end;
+          end;
         for i:=0 to length(RightSet.Ranges)-1 do
         for i:=0 to length(RightSet.Ranges)-1 do
-          for Int:=RightSet.Ranges[i].RangeStart to RightSet.Ranges[i].RangeEnd do
+          begin
+          Int:=RightSet.Ranges[i].RangeStart;
+          while Int<=RightSet.Ranges[i].RangeEnd do
+            begin
             if LeftSet.IndexOfRange(Int)<0 then
             if LeftSet.IndexOfRange(Int)<0 then
-              TResEvalSetInt(Result).Add(Int,Int);
+              TResEvalSet(Result).Add(Int,Int);
+            inc(Int);
+            end;
+          end;
         end;
         end;
       end
       end
     else
     else
@@ -2752,19 +2796,20 @@ begin
 end;
 end;
 
 
 function TResExprEvaluator.EvalSetParamsExpr(Expr: TParamsExpr;
 function TResExprEvaluator.EvalSetParamsExpr(Expr: TParamsExpr;
-  Flags: TResEvalFlags): TResEvalSetInt;
+  Flags: TResEvalFlags): TResEvalSet;
 var
 var
   i: Integer;
   i: Integer;
   RangeStart, RangeEnd: MaxPrecInt;
   RangeStart, RangeEnd: MaxPrecInt;
   Value: TResEvalValue;
   Value: TResEvalValue;
-  ok: Boolean;
+  ok, OnlyConstElements: Boolean;
   El: TPasExpr;
   El: TPasExpr;
 begin
 begin
   {$IFDEF VerbosePasResEval}
   {$IFDEF VerbosePasResEval}
   writeln('TResExprEvaluator.EvalSetParamsExpr length(Expr.Params)=',length(Expr.Params));
   writeln('TResExprEvaluator.EvalSetParamsExpr length(Expr.Params)=',length(Expr.Params));
   {$ENDIF}
   {$ENDIF}
-  Result:=TResEvalSetInt.Create;
+  Result:=TResEvalSet.Create;
   Value:=nil;
   Value:=nil;
+  OnlyConstElements:=true;
   ok:=false;
   ok:=false;
   try
   try
     for i:=0 to length(Expr.Params)-1 do
     for i:=0 to length(Expr.Params)-1 do
@@ -2777,9 +2822,12 @@ begin
       if Value=nil then
       if Value=nil then
         begin
         begin
         // element is not a const -> the set is not a const
         // element is not a const -> the set is not a const
-        exit;
+        OnlyConstElements:=false;
+        continue;
         end;
         end;
-      writeln('TResExprEvaluator.EvalSetParamsExpr ',i,' of ',length(Expr.Params),' Value=',Value.AsDebugString);
+      {$IFDEF VerbosePasResEval}
+      //writeln('TResExprEvaluator.EvalSetParamsExpr ',i,' of ',length(Expr.Params),' Value=',Value.AsDebugString);
+      {$ENDIF}
       case Value.Kind of
       case Value.Kind of
       revkBool:
       revkBool:
         begin
         begin
@@ -2881,9 +2929,17 @@ begin
         RaiseNotYetImplemented(20170713143422,El);
         RaiseNotYetImplemented(20170713143422,El);
       end;
       end;
 
 
+      if Result.Intersects(RangeStart,RangeEnd)>=0 then
+        begin
+        {$IF defined(VerbosePasResEval) or defined(VerbosePasResolver)}
+        writeln('TResExprEvaluator.EvalSetParamsExpr Value=',Value.AsDebugString,' Range=',RangeStart,'..',RangeEnd,' Result=',Result.AsDebugString);
+        {$ENDIF}
+        RaiseMsg(20170714141326,nRangeCheckInSetConstructor,
+          sRangeCheckInSetConstructor,[],El);
+        end;
       Result.Add(RangeStart,RangeEnd);
       Result.Add(RangeStart,RangeEnd);
       end;
       end;
-    ok:=true;
+    ok:=OnlyConstElements;
   finally
   finally
     ReleaseEvalValue(Value);
     ReleaseEvalValue(Value);
     if not ok then
     if not ok then
@@ -4104,34 +4160,34 @@ begin
   end;
   end;
 end;
 end;
 
 
-{ TResEvalSetInt }
+{ TResEvalSet }
 
 
-constructor TResEvalSetInt.Create;
+constructor TResEvalSet.Create;
 begin
 begin
   inherited Create;
   inherited Create;
   Kind:=revkSetOfInt;
   Kind:=revkSetOfInt;
 end;
 end;
 
 
-constructor TResEvalSetInt.CreateEmpty(aSet: TResEvalSetInt);
+constructor TResEvalSet.CreateEmpty(aSet: TResEvalSet);
 begin
 begin
   ElKind:=aSet.ElKind;
   ElKind:=aSet.ElKind;
   IdentEl:=aSet.IdentEl;
   IdentEl:=aSet.IdentEl;
 end;
 end;
 
 
-function TResEvalSetInt.Clone: TResEvalValue;
+function TResEvalSet.Clone: TResEvalValue;
 var
 var
-  RS: TResEvalSetInt;
+  RS: TResEvalSet;
   i: Integer;
   i: Integer;
 begin
 begin
   Result:=inherited Clone;
   Result:=inherited Clone;
-  TResEvalSetInt(Result).ElKind:=ElKind;
-  RS:=TResEvalSetInt(Result);
+  TResEvalSet(Result).ElKind:=ElKind;
+  RS:=TResEvalSet(Result);
   SetLength(RS.Ranges,length(Ranges));
   SetLength(RS.Ranges,length(Ranges));
   for i:=0 to length(Ranges)-1 do
   for i:=0 to length(Ranges)-1 do
     RS.Ranges[i]:=Ranges[i];
     RS.Ranges[i]:=Ranges[i];
 end;
 end;
 
 
-function TResEvalSetInt.AsString: string;
+function TResEvalSet.AsString: string;
 var
 var
   i: Integer;
   i: Integer;
 begin
 begin
@@ -4146,7 +4202,7 @@ begin
   Result:=Result+']';
   Result:=Result+']';
 end;
 end;
 
 
-function TResEvalSetInt.ElementAsString(El: MaxPrecInt): string;
+function TResEvalSet.ElementAsString(El: MaxPrecInt): string;
 begin
 begin
   case ElKind of
   case ElKind of
     revskEnum: Result:=TPasEnumValue(TPasEnumType(IdentEl).Values[El]).Name;
     revskEnum: Result:=TPasEnumValue(TPasEnumType(IdentEl).Values[El]).Name;
@@ -4164,7 +4220,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TResEvalSetInt.Add(RangeStart, RangeEnd: MaxPrecInt): boolean;
+function TResEvalSet.Add(RangeStart, RangeEnd: MaxPrecInt): boolean;
 var
 var
   StartIndex, l, EndIndex: Integer;
   StartIndex, l, EndIndex: Integer;
   Item: TItem;
   Item: TItem;
@@ -4275,7 +4331,7 @@ begin
   {$ENDIF}
   {$ENDIF}
 end;
 end;
 
 
-function TResEvalSetInt.IndexOfRange(Index: MaxPrecInt; FindInsertPos: boolean
+function TResEvalSet.IndexOfRange(Index: MaxPrecInt; FindInsertPos: boolean
   ): integer;
   ): integer;
 var
 var
   l, r, m: Integer;
   l, r, m: Integer;
@@ -4303,7 +4359,18 @@ begin
     exit(m);
     exit(m);
 end;
 end;
 
 
-procedure TResEvalSetInt.ConsistencyCheck;
+function TResEvalSet.Intersects(RangeStart, RangeEnd: MaxPrecInt): integer;
+var
+  Index: Integer;
+begin
+  Index:=IndexOfRange(RangeStart,true);
+  if (Index=length(Ranges)) or (Ranges[Index].RangeStart>RangeEnd) then
+    Result:=-1
+  else
+    Result:=Index;
+end;
+
+procedure TResEvalSet.ConsistencyCheck;
 
 
   procedure E(Msg: string);
   procedure E(Msg: string);
   begin
   begin

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

@@ -8383,7 +8383,7 @@ var
   ArrayEl: TPasArrayType;
   ArrayEl: TPasArrayType;
   Value: TResEvalValue;
   Value: TResEvalValue;
   EnumType: TPasEnumType;
   EnumType: TPasEnumType;
-  aSet: TResEvalSetInt;
+  aSet: TResEvalSet;
   Int: MaxPrecInt;
   Int: MaxPrecInt;
   bt: TResolverBaseType;
   bt: TResolverBaseType;
   MinInt, MaxInt: int64;
   MinInt, MaxInt: int64;
@@ -8454,7 +8454,7 @@ begin
     case Value.Kind of
     case Value.Kind of
     revkSetOfInt:
     revkSetOfInt:
       begin
       begin
-      aSet:=TResEvalSetInt(Value);
+      aSet:=TResEvalSet(Value);
       if length(aSet.Ranges)=0 then
       if length(aSet.Ranges)=0 then
         RaiseXExpectedButYFound(20170601201637,'ordinal value',Value.AsString,Param);
         RaiseXExpectedButYFound(20170601201637,'ordinal value',Value.AsString,Param);
       if Proc.BuiltIn=bfLow then
       if Proc.BuiltIn=bfLow then

+ 13 - 0
packages/fcl-passrc/tests/tcresolver.pas

@@ -201,6 +201,7 @@ type
     Procedure TestByteRangeFail;
     Procedure TestByteRangeFail;
     Procedure TestCustomIntRangeFail;
     Procedure TestCustomIntRangeFail;
     Procedure TestIntSet_Const;
     Procedure TestIntSet_Const;
+    Procedure TestIntSet_ConstDuplicateElement;
 
 
     // strings
     // strings
     Procedure TestChar_Ord;
     Procedure TestChar_Ord;
@@ -2405,6 +2406,18 @@ begin
   CheckResolverUnexpectedHints;
   CheckResolverUnexpectedHints;
 end;
 end;
 
 
+procedure TTestResolver.TestIntSet_ConstDuplicateElement;
+begin
+  {$IFDEF EnablePasResRangeCheck}
+  StartProgram(false);
+  Add([
+  'const',
+  '  s1 = [1,1..2];',
+  'begin']);
+  CheckResolverException(sRangeCheckInSetConstructor,nRangeCheckInSetConstructor);
+  {$ENDIF}
+end;
+
 procedure TTestResolver.TestChar_Ord;
 procedure TTestResolver.TestChar_Ord;
 begin
 begin
   StartProgram(false);
   StartProgram(false);