Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_CLngPtr pseudo-function #580

Closed
wants to merge 1 commit into from
Closed

Conversation

a740g
Copy link
Contributor

@a740g a740g commented Nov 27, 2024

In QB64, the usage of _OFFSET variables in expressions is intentionally limited, with guardrails in place to discourage improper use. These restrictions are designed to prevent users from inadvertently performing invalid pointer arithmetic that could lead to reading or writing in unauthorized areas of memory. This is all good. However, there are scenarios where using _OFFSET variables in pointer arithmetic becomes necessary. For a detailed discussion, refer to issue #123.

Currently, these guardrails force users to rely on inefficient conversions or questionable hacks, both of which are undesirable.

Expensive conversion:

DIM m as _MEM

b&& = _CV(_INTEGER64, _MK$(_INTEGER64, m.SIZE))

Hack:

$IF 32BIT THEN
    FUNCTION CLngPtr~& ALIAS "uintptr_t" (BYVAL o AS _OFFSET)
$ELSE
    FUNCTION CLngPtr~&& ALIAS "uintptr_t" (BYVAL o AS _OFFSET)
$END IF 

This PR introduces the _CLngPtr pseudo-function, which allows users to directly retrieve the value of an _OFFSET variable and allows its usage in expressions where usage of _OFFSET was previously not allowed. Internally, no actual function call is performed. The name is inspired by Microsoft's CLngPtr, which does something similar.

result = _CLngPtr(offset%&)

@a740g a740g added the enhancement New feature or request label Nov 27, 2024
@a740g a740g self-assigned this Nov 27, 2024
Copy link
Member

@RhoSigma-QB64 RhoSigma-QB64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just don't know if I like the name. When reading _CLngPtr my immediate thought is more in the direction of obtaining a pointer from the given LONG variable, hence _OFFSET(lvar&) or in C ptrszint = &somelongvar. The name is also too similar to CLng which does something completely different.

But as this pseudo function effectively just makes an explicit type cast I'd probably prefer something more straight forward to that behavior, e.g. simply _OffToInt, _OffsetAsNumber, _OffsetVal or something similar.

@mkilgore
Copy link
Contributor

I second @RhoSigma-QB64's thoughts - especially because "pointer" is not a word we use in QB64, so I think it's a bit extra confusing. I'd be fine with @RhoSigma-QB64's name, though I'd mention we could potentially expand this and introduce a new _Cast(val, type) type of command (and allow _OFFSETs to be cast to _Unsigned _Integer64``). I don't think it's that out of the question, we already have the QB45 commands CINT, CDBL, CSNG, CLNG`, etc. which allow casting for all the original types, but I don't think we have any of these for the new types or a generic command for them.

Perhaps instead of this we could consider just removing the restrictions on _OFFSET? I've mentioned it before that I think we should have a separate _SIZE type that is similar to size_t - currently we use _OFFSET for both pointers and size_t values. If we don't want to go through with adding a _SIZE type though (and I'm not sure we can do it in a non-breaking way anyway) then removing the restrictions on _OFFSET so that you can use it like a size_t would probably make sense.

@a740g
Copy link
Contributor Author

a740g commented Nov 27, 2024

I have had trouble picking the name, eventually settling for something Microsoft uses, thinking it may be familiar. But I think I like @mkilgore's suggestion better now. A _Cast command would be more useful.

Honestly, I am unsure why we have restrictions on _OFFSET. However, after looking at the code, I found multiple places where it is checked if we are dealing with an _OFFSET or not. Notably:

'Offset protection:

IF sourcetyp AND ISOFFSET THEN

'*_OFFSET exceptions*

IF sourcetyp AND ISOFFSET THEN

And there are a few more. I did consider removing those. But I am not really sure what that'll break.

@mkilgore
Copy link
Contributor

I think in general the _OFFSET restrictions make sense if we consider it to just be a pointer type, like a char *. Storing regular integers in a char * is a messy way to do things and makes it easy to get values mixed up and deref a non-pointer type. Keeping a clean separation helps avoid big errors, and in C and C++ storing numbers in a char * is almost never necessary so it's not a big deal.

The issue for QB64 is that it breaks this thinking with _MEM.SIZE, because that value is obviously not a pointer but still has the _OFFSET type. If we could change _MEM.SIZE (and the other entries) to a new variable type in a non-breaking way then that would be the best solution, but I'm pretty sure we can't do that without breaking existing code (it might be worth a try though). If we can't introduce a new type, then removing the restrictions of _OFFSET and allowing it to act like both a char * and size_t probably makes the most sense.

@a740g
Copy link
Contributor Author

a740g commented Nov 28, 2024

Closing this based on discussion above. Will open a fresh PR with _OFFSET restrictions removed and add new tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants