Explorar el Código

* handle constant folding correctly for <pointer>+<ord. constant>+<ord. constant>, resolves #39332

florian hace 3 años
padre
commit
3069d74ecc
Se han modificado 2 ficheros con 45 adiciones y 1 borrados
  1. 4 1
      compiler/nadd.pas
  2. 41 0
      tests/webtbs/tw39332.pp

+ 4 - 1
compiler/nadd.pas

@@ -541,7 +541,10 @@ implementation
                 but this is only useful if no pointer operation is done }
               left:=ctypeconvnode.create_internal(left,resultdef);
               do_typecheckpass(left);
-            end;
+            end
+          else if tpointerdef(resultdef).pointeddef.size>1 then
+          { the constants were already multiplied by the pointer element size }
+            left:=cmoddivnode.create(divn,left,cordconstnode.create(tpointerdef(resultdef).pointeddef.size,left.resultdef,false));
           right:=left;
           left:=hp;
           result:=GetCopyAndTypeCheck;

+ 41 - 0
tests/webtbs/tw39332.pp

@@ -0,0 +1,41 @@
+{ %OPT=-O3 }
+{$mode objfpc} {$h+} {$typedaddress on}
+type
+	pBaseType = ^BaseType;
+	BaseType = uint32; // can be replaced with an arbitrary-sized array or record
+
+procedure Check(pstart, px: pBaseType; refIx: SizeInt; const desc: string);
+var
+	ix: SizeInt;
+begin
+	ix := px - pstart;
+	writeln(desc, ' points at element #', ix);
+	if ix = refIx then
+		writeln('ok')
+	else
+      begin
+		writeln('WRONG, must be #', refIx);
+        halt(1);
+      end;
+	writeln;
+end;
+
+var
+	x: array[0 .. 19] of BaseType;
+	p: pBaseType;
+
+begin
+	p := pBaseType(x);
+	Check(p, p + 2,         2,  'p + 2');
+	Check(p, p + 2 + 3,     5,  'p + 2 + 3');
+	Check(p, p + 2 + 3 + 5, 10, 'p + 2 + 3 + 5');
+
+	// These casts don't help.
+	Check(p, pBaseType(pBaseType(p + 2) + 3) + 5, 10, 'pBaseType(pBaseType(p + 2) + 3) + 5');
+
+	// These work, but prevent constant folding.
+	Check(p, pBaseType(pointer(pBaseType(pointer(p + 2)) + 3)) + 5, 10, 'pBaseType(pointer(pBaseType(pointer(p + 2)) + 3)) + 5');
+
+	Check(p, p + (2 + 3 + 5),   10, 'p + (2 + 3 + 5)');
+	Check(p, p + 2 + 3 + 5 + 7, 17, 'p + 2 + 3 + 5 + 7');
+end.