Browse Source

pastojs: fixed range check of o.aArray[index]

git-svn-id: trunk@40177 -
Mattias Gaertner 6 years ago
parent
commit
2aab88ee4e

+ 10 - 0
packages/fcl-passrc/src/pastree.pp

@@ -236,6 +236,7 @@ type
     destructor Destroy; override;
     destructor Destroy; override;
     procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
     procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
       const Arg: Pointer); override;
       const Arg: Pointer); override;
+    class function IsRightSubIdent(El: TPasElement): boolean;
   end;
   end;
 
 
   { TPrimitiveExpr }
   { TPrimitiveExpr }
@@ -5062,6 +5063,15 @@ begin
   ForEachChildCall(aMethodCall,Arg,right,false);
   ForEachChildCall(aMethodCall,Arg,right,false);
 end;
 end;
 
 
+class function TBinaryExpr.IsRightSubIdent(El: TPasElement): boolean;
+var
+  Bin: TBinaryExpr;
+begin
+  if (El=nil) or not (El.Parent is TBinaryExpr) then exit(false);
+  Bin:=TBinaryExpr(El.Parent);
+  Result:=(Bin.right=El) and (Bin.OpCode=eopSubIdent);
+end;
+
 { TParamsExpr }
 { TParamsExpr }
 
 
 function TParamsExpr.GetDeclaration(full: Boolean): string;
 function TParamsExpr.GetDeclaration(full: Boolean): string;

+ 2 - 5
packages/pastojs/src/fppas2js.pp

@@ -7431,10 +7431,7 @@ var
 
 
       CallEx:=CreateCallExpression(El);
       CallEx:=CreateCallExpression(El);
       try
       try
-        if IsRangeCheck
-            and (not (El.Parent is TBinaryExpr)
-              or (TBinaryExpr(El.Parent).right<>El)
-              or (TBinaryExpr(El.Parent).OpCode<>eopSubIdent)) then
+        if IsRangeCheck and not TBinaryExpr.IsRightSubIdent(El) then
           begin
           begin
           // read s[index]  ->  rtl.rcCharAt(s,index-1)
           // read s[index]  ->  rtl.rcCharAt(s,index-1)
           CallEx.Expr:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTL]+'.'+FBuiltInNames[pbifnRangeCheckGetCharAt],El);
           CallEx.Expr:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTL]+'.'+FBuiltInNames[pbifnRangeCheckGetCharAt],El);
@@ -7649,7 +7646,7 @@ var
                 and (bsRangeChecks in AContext.ScannerBoolSwitches)
                 and (bsRangeChecks in AContext.ScannerBoolSwitches)
                 and (AContext.Access in [caRead,caAssign]);
                 and (AContext.Access in [caRead,caAssign]);
 
 
-      if IsRangeCheck then
+      if IsRangeCheck and not TBinaryExpr.IsRightSubIdent(El) then
         begin
         begin
         // read a[i,j,k]  ->  rtl.rcArrR(a,i,j,k)
         // read a[i,j,k]  ->  rtl.rcArrR(a,i,j,k)
         // assign a[i,j,k]=RHS  ->  rtl.rcArrW(a,i,j,k,RHS)
         // assign a[i,j,k]=RHS  ->  rtl.rcArrW(a,i,j,k,RHS)

+ 15 - 0
packages/pastojs/tests/tcmodules.pas

@@ -22518,6 +22518,9 @@ begin
   '  TArrByte = array[byte] of Ten;',
   '  TArrByte = array[byte] of Ten;',
   '  TArrChar = array[''0''..''9''] of Ten;',
   '  TArrChar = array[''0''..''9''] of Ten;',
   '  TArrByteChar = array[byte,''0''..''9''] of Ten;',
   '  TArrByteChar = array[byte,''0''..''9''] of Ten;',
+  '  TObject = class',
+  '    A: TArr;',
+  '  end;',
   'procedure DoIt;',
   'procedure DoIt;',
   'var',
   'var',
   '  Arr: TArr;',
   '  Arr: TArr;',
@@ -22527,6 +22530,7 @@ begin
   '  ArrByteChar: TArrByteChar;',
   '  ArrByteChar: TArrByteChar;',
   '  i: Ten;',
   '  i: Ten;',
   '  c: char;',
   '  c: char;',
+  '  o: tobject;',
   'begin',
   'begin',
   '  i:=Arr[1];',
   '  i:=Arr[1];',
   '  i:=ArrByteChar[1,''2''];',
   '  i:=ArrByteChar[1,''2''];',
@@ -22538,12 +22542,21 @@ begin
   '  ArrChar[c]:=ArrChar[c];',
   '  ArrChar[c]:=ArrChar[c];',
   '  ArrByteChar[7,''7'']:=ArrByteChar[7,''7''];',
   '  ArrByteChar[7,''7'']:=ArrByteChar[7,''7''];',
   '  ArrByteChar[i,c]:=ArrByteChar[i,c];',
   '  ArrByteChar[i,c]:=ArrByteChar[i,c];',
+  '  o.a[i]:=o.a[i];',
   'end;',
   'end;',
   'begin',
   'begin',
   '']);
   '']);
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestRangeChecks_ArrayIndex',
   CheckSource('TestRangeChecks_ArrayIndex',
     LinesToStr([ // statements
     LinesToStr([ // statements
+    'rtl.createClass($mod, "TObject", null, function () {',
+    '  this.$init = function () {',
+    '    this.A = [];',
+    '  };',
+    '  this.$final = function () {',
+    '    this.A = undefined;',
+    '  };',
+    '});',
     'this.DoIt = function () {',
     'this.DoIt = function () {',
     '  var Arr = [];',
     '  var Arr = [];',
     '  var ArrArr = [];',
     '  var ArrArr = [];',
@@ -22552,6 +22565,7 @@ begin
     '  var ArrByteChar = rtl.arraySetLength(null, 0, 256, 10);',
     '  var ArrByteChar = rtl.arraySetLength(null, 0, 256, 10);',
     '  var i = 0;',
     '  var i = 0;',
     '  var c = "";',
     '  var c = "";',
+    '  var o = null;',
     '  i = rtl.rc(Arr[1], 1, 10);',
     '  i = rtl.rc(Arr[1], 1, 10);',
     '  i = rtl.rc(ArrByteChar[1][2], 1, 10);',
     '  i = rtl.rc(ArrByteChar[1][2], 1, 10);',
     '  Arr[1] = rtl.rc(Arr[1], 1, 10);',
     '  Arr[1] = rtl.rc(Arr[1], 1, 10);',
@@ -22562,6 +22576,7 @@ begin
     '  rtl.rcArrW(ArrChar, c.charCodeAt() - 48, rtl.rcArrR(ArrChar, c.charCodeAt() - 48));',
     '  rtl.rcArrW(ArrChar, c.charCodeAt() - 48, rtl.rcArrR(ArrChar, c.charCodeAt() - 48));',
     '  ArrByteChar[7][7] = rtl.rc(ArrByteChar[7][7], 1, 10);',
     '  ArrByteChar[7][7] = rtl.rc(ArrByteChar[7][7], 1, 10);',
     '  rtl.rcArrW(ArrByteChar, i, c.charCodeAt() - 48, rtl.rcArrR(ArrByteChar, i, c.charCodeAt() - 48));',
     '  rtl.rcArrW(ArrByteChar, i, c.charCodeAt() - 48, rtl.rcArrR(ArrByteChar, i, c.charCodeAt() - 48));',
+    '  o.A[i] = rtl.rc(o.A[i], 1, 10);',
     '};',
     '};',
     '']),
     '']),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main