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

mkString writes wild pointer levels in reverse order (mixes up type qualifiers) #161

Open
john-h-kastner opened this issue Jul 8, 2020 · 8 comments
Labels
bug Something isn't working type-qualifier

Comments

@john-h-kastner
Copy link
Collaborator

It looks like we mess up the order of consts and *s when rewriting.

int *const *a = 1;
int *const **b = &a;

becomes

int *const *a = 1;
_Ptr<int**const > b =  &a;

but checkedc-clang complains with

test.checked.c:2:19: error: initializing '_Ptr<int **const>' with an expression of incompatible type 'int *const **'
_Ptr<int**const > b =  &a;
@sroy4899
Copy link

sroy4899 commented Jul 8, 2020

Out of curiosity, do you think the following conversion would be right? It seems to compile with the checked-c compiler and makes sense to me.

_Ptr<int *const *> b =  &a;

This preserves the information that a is a pointer to a const pointer to int.

@john-h-kastner
Copy link
Collaborator Author

I think that's the correct conversion, but I can never remember the correct order to read C type qualifiers.

@sroy4899
Copy link

sroy4899 commented Jul 8, 2020

Hear hear. Took me several visits to https://cdecl.org/ (credit to Aaron for linking me this) to wrap my head around this. Obviously, doesn't quite hold up to adding a bunch of _Ptr annotations, but good for the basics, I suppose

@john-h-kastner john-h-kastner added the bug Something isn't working label Jul 8, 2020
@mwhicks1
Copy link
Member

What is the equivalent of int *const x as a _Ptr ? Maybe _Ptr<int> const x ?

@john-h-kastner
Copy link
Collaborator Author

What is the equivalent of int *const x as a _Ptr ? Maybe _Ptr<int> const x ?

Both const _Ptr<Int> x and _Ptr<int> const x should work.

@sroy4899
Copy link

Did you have a code example where you tested that? I tried it out and can't seem to get it to compile if I use it after. So for the following code:

int y = 2;
_Ptr<int> const x = &y; 
*x = 3;

I believe I'm using everything safely here, since x is a const pointer and the value it points to is free to change (if we're right), but it doesn't compile for the following reasons:

foo.c:4:2: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
*x = 3;
 ^
foo.c:4:2: error: redefinition of 'x' with a different type: 'int *' vs '_Ptr<int> const'
foo.c:3:17: note: previous definition is here
_Ptr<int> const x = &y; 

From the error, I'm assuming some sort of implicit cast to (int *) is happening when we dereference, but that should only happen if the thing we're pointing to is a const int right? Except the warning is equally confusing because it says that the type specifier is "missing", which leads me to believe that x isn't being defined at all.

@john-h-kastner
Copy link
Collaborator Author

You need put *x = 3 in a function, otherwise it gets parsed the same as int *x = 3 which is why it complains about a redefinition.

@mattmccutchen-cci mattmccutchen-cci changed the title Pointers to const pointers 3C writes wild pointer levels in reverse order (mixes up type qualifiers) Oct 2, 2021
@mattmccutchen-cci mattmccutchen-cci changed the title 3C writes wild pointer levels in reverse order (mixes up type qualifiers) mkString writes wild pointer levels in reverse order (mixes up type qualifiers) Oct 2, 2021
@mattmccutchen-cci
Copy link
Member

I seem to have rediscovered this problem while working on the mkString code in #714 (thanks to John for pointing me to the existing issue thread after I added the problem as a sub-issue of #703). mkString is writing the wild pointer levels in reverse order because it traverses type levels from outer to inner and prints wild pointer levels to Ss in the order they are seen, i.e., left to right, so the outermost level ends up on the left. It should be on the right. This manifests as type qualifiers getting reversed; I don't know if it causes any other observable problems.

In the original example, the * and the * const get swapped going from the type of a to the interior of the _Ptr type of b. It becomes easier to see what's going on if we have qualifiers at both levels:

void test(void) {
  int *const *volatile q = 1;
  int *const *volatile *p = &q;
}

Output:

void test(void) {
  int *const *volatile q = 1;
  _Ptr<int *volatile *const > p = &q;
}

I'll post some additional information on #703.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working type-qualifier
Projects
None yet
Development

No branches or pull requests

4 participants