Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2012-12

Warning: Conversion between ordinals and pointers is not portable

7 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Martin

Ok now I am curious

SomePointer := Pointer(PtrInt(SomeNumber))
SomePointer := Pointer(PtrUInt(SomeNumber))

The 2nd gives the warning.
Warning: Conversion between ordinals and pointers is not portable

But the first does not.

Yet PtrInt/PtrUInt are both the size of pointer?

Reply by email

Jonas Maebe
to Martin
Martin wrote 12 lines
Ok now I am curious SomePointer := Pointer(PtrInt(SomeNumber)) SomePointer := Pointer(PtrUInt(SomeNumber)) The 2nd gives the warning. Warning: Conversion between ordinals and pointers is not portable But the first does not. Yet PtrInt/PtrUInt are both the size of pointer?

As always when asking about help with something the compiler does, post a complete and compilable program that demonstrates your question. The following code does not produce any warning (it will produce hints):

const
  somenumber: shortint=2;
var
  somepointer: pointer;
begin
  SomePointer := Pointer(PtrInt(SomeNumber));
  SomePointer := Pointer(PtrUInt(SomeNumber))
end.

It also doesn't produce a warning either if the type of somenumber is changed to byte, longint or int64, nor when changing somenumber into a symbolic constant; all regardless of whether I compile for 32 or 64 bit.

Jonas

Reply by email

Martin
to Jonas Maebe
Jonas Maebe wrote
As always when asking about help with something the compiler does, post a complete and compilable program that demonstrates your question. The following code does not produce any warning (it will produce hints):

Sorry about that. I had to extract it from same bigger code.

If compiled, with PtrUint (as is below)

Free Pascal Compiler version 2.6.0 [2012/01/04] for i386 Compiling C:\Users\martin\AppData\Local\Temp\project1.lpr project1.lpr(11,28) Warning: Variable "p" does not seem to be initialized project1.lpr(11,11) Warning: Conversion between ordinals and pointers is not portable
project1.lpr(9,5) Note: Local variable "darr" is assigned but never used Linking C:\Users\martin\AppData\Local\Temp\project1.exe

If replace the type
type IPointer = PtrInt;

Free Pascal Compiler version 2.6.0 [2012/01/04] for i386 Compiling C:\Users\martin\AppData\Local\Temp\project1.lpr project1.lpr(11,28) Warning: Variable "p" does not seem to be initialized project1.lpr(11,11) Hint: Conversion between ordinals and pointers is not portable
project1.lpr(9,5) Note: Local variable "darr" is assigned but never used Linking C:\Users\martin\AppData\Local\Temp\project1.exe

So actually the message is just downgraded from Warning to Hint.

and the full command line as issued by Lazarus:
fpc.exe -MObjFPC -Scghi -O1 -gw2 -godwarfsets -gl -gh -vewnhi -Filib\i386-win32 -FUlib\i386-win32\ -l
C:\Users\martin\AppData\Local\Temp\project1.lpr"

If I remove the " - PointerSize2" it is always a hint. But the location (11,11) doe not point to thin, it points to the uppercase "P" of this most outer "Pointer()"typecast

program Project1;
{$mode objfpc}{$H+}
uses Classes;
type IPointer = PtrUInt;
const
   PointerSize = IPointer({$IFDEF CPU64}8{$ELSE}4{$ENDIF});
   PointerSize2 = IPointer(2*PointerSize);
var
   p,darr: Pointer;
begin
   darr := Pointer(IPointer(p^) - PointerSize2);
end.

Reply by email

Jonas Maebe
to Martin
Martin wrote 11 lines
If compiled, with PtrUint (as is below) Free Pascal Compiler version 2.6.0 [2012/01/04] for i386 Compiling C:\Users\martin\AppData\Local\Temp\project1.lpr project1.lpr(11,28) Warning: Variable "p" does not seem to be initialized project1.lpr(11,11) Warning: Conversion between ordinals and pointers is not portable project1.lpr(9,5) Note: Local variable "darr" is assigned but never used Linking C:\Users\martin\AppData\Local\Temp\project1.exe

That's because cardinal-cardinal results in an int64, because of a.o. http://bugs.freepascal.org/view.php?id=8321

Show quoted text 14 lines
If replace the type type IPointer = PtrInt; Free Pascal Compiler version 2.6.0 [2012/01/04] for i386 Compiling C:\Users\martin\AppData\Local\Temp\project1.lpr project1.lpr(11,28) Warning: Variable "p" does not seem to be initialized project1.lpr(11,11) Hint: Conversion between ordinals and pointers is not portable project1.lpr(9,5) Note: Local variable "darr" is assigned but never used Linking C:\Users\martin\AppData\Local\Temp\project1.exe So actually the message is just downgraded from Warning to Hint.

Yes, that's by design. The compiler has no special knowledge about the ptrint or ptruint types. It is almost impossible to fix all hints for non-trivial programs, and they only exist to help find possibly suspicious locations in code (and typecasting an integer into a pointer is such an expression). You can always disable a particular hint with -vqXXX if you are not interested in it.

Show quoted text 8 lines
and the full command line as issued by Lazarus: fpc.exe -MObjFPC -Scghi -O1 -gw2 -godwarfsets -gl -gh -vewnhi -Filib \i386-win32 -FUlib\i386-win32\ -l C:\Users\martin\AppData\Local\Temp \project1.lpr" If I remove the " - PointerSize2" it is always a hint. But the location (11,11) doe not point to thin, it points to the uppercase "P" of this most outer "Pointer()"typecast

The typecast of the integer expression to a pointer is what triggers the warning/hint.

Jonas

Reply by email

Martin
to Jonas Maebe
Jonas Maebe wrote 14 lines
That's because cardinal-cardinal results in an int64, because of a.o. http://bugs.freepascal.org/view.php?id=8321 > > So actually the message is just downgraded from Warning to Hint. Yes, that's by design. The compiler has no special knowledge about the ptrint or ptruint types. It is almost impossible to fix all hints for non-trivial programs, and they only exist to help find possibly suspicious locations in code (and typecasting an integer into a pointer is such an expression). You can always disable a particular hint with -vqXXX if you are not interested in it.

I have no issue with the hint. I understand Ptr(u)Int are no different from all other int types. Just aliases.

I now see that I get the warning, if the type-to-be-casted is 64 bit and
I am on a 32bit system.
program Project1;
{$mode objfpc}{$H+}
var
   p: Pointer;
   a: int64; //qword;
begin
   p := Pointer(a);
end.
project1.lpr(7,8) Warning: Conversion between ordinals and pointers is
not portable

Yet what I do not understand, is why I get that message as warning (as opposed to a hint). If I understand it right (I have not tested, maybe it gives a warning on 64 bit target too, if so ignore the rest), and I compile for a 64bit target, then it downgrades to a hint again?

The only difference is, that in the above example, if compiled for a 32 bit system, I already may have broken code. But then what it actually means is that I should get warning about a truncating the value.

   b := byte(a);

Gives no also truncates the warning. What is then special about potentially truncating a value by using pointer(a)? If "pointer(a)" is worth a warning (instead of a hint, why isn't byte(a)?

---
Not saying it needs to change. But trying to figure out the reason behind.

Reply by email

Jonas Maebe
to Martin
Martin wrote 5 lines
Yet what I do not understand, is why I get that message as warning (as opposed to a hint). If I understand it right (I have not tested, maybe it gives a warning on 64 bit target too, if so ignore the rest), and I compile for a 64bit target, then it downgrades to a hint again?

Yes. If you typecast an integer to a pointer and both have the same size, you get a hint. If they have a different size, you get a warning.

Show quoted text 7 lines
The only difference is, that in the above example, if compiled for a 32 bit system, I already may have broken code. But then what it actually means is that I should get warning about a truncating the value. b := byte(a); Gives no 's because truncating integers cannot result in invalid addresses.

The warning was added to help people moving from 32 bit to 64 bit systems and using longint typecasts in their programs to convert between addresses and integers. There are very few cases whereby discarding the upper 32 bit of a pointer is intended or results in valid code.

It also truncates the warning. What is then special about potentially truncating a value by using pointer(a)? If "pointer(a)" is worth a warning (instead of a hint, why isn't byte(a)?

Because there never was a migration from a system whereby int64 was the same size as a byte and now it isn't anymore, and there are many common cases whereby discarding part of an integer value is part of an algorithm.

Jonas

Reply by email

Martin
to Jonas Maebe
Jonas Maebe wrote 27 lines
On 06 Dec 2012, at 14:03, Martin wrote: > Yet what I do not understand, is why I get that message as warning > (as opposed to a hint). If I understand it right (I have not tested, > maybe it gives a warning on 64 bit target too, if so ignore the > rest), and I compile for a 64bit target, then it downgrades to a > hint again? Yes. If you typecast an integer to a pointer and both have the same size, you get a hint. If they have a different size, you get a warning. > The only difference is, that in the above example, if compiled for a > 32 bit system, I already may have broken code. But then what it > actually means is that I should get warning about a truncating the > value. > > b := byte(a); > Gives no warning at all. That's because truncating integers cannot result in invalid addresses. The warning was added to help people moving from 32 bit to 64 bit systems and using longint typecasts in their programs to convert between addresses and integers. There are very few cases whereby discarding the upper 32 bit of a pointer is intended or results in valid code.

Ok, thanks.

It was only that I was working on 3cd party code, with many pointer casts. And some did warn, some not (add to that that the IDE did hide the hints. And I couldn't work out why I only got some warnings, and not others.

Reply by email