0

The from_base function returns the memory address from the base to a selected value in a program. I want to retrieve this value and return it in a function, however, I am getting a warning that says integer to pointer cast pessimism optimization opportunities.

DWORD chat::client() {
    return *reinterpret_cast<DWORD*>(core::from_base(offsets::chat::client));
}

I am also getting this warning when casting a function from the program:

auto og_print = reinterpret_cast<chat::fn_print_chat>(core::from_base(offsets::chat::print));

I don't understand why I am getting a warning from clang-tidy about integer to pointer cast pessimism optimization opportunities

performance-no-int-to-ptr

I looked it up, but I can't figure it out. The code works, and gets the correct value. I am just concerned about the warning.

Dany Gagnon
  • 102
  • 1
  • 9
  • 2
    _"returns the memory address from the base to a selected value"_: What exactly does that mean? Why does the function return an integer instead of a pointer? – user17732522 Feb 12 '22 at 22:04
  • Basically, the `from_base` function returns the base address from the application using `GetModuleHandle` and adds an offset to the address that contains the chat pointer. – Dany Gagnon Feb 12 '22 at 22:28
  • 2
    I would suggest having `from_base` return a `void*` instead even if internally it uses integer arithmetic. That way there will be only one point where this warning needs to be suppressed and a `void*` is much more intuitive than an integer. Since the pointer is external to the code, the pessimization is probably there anyway. But isn't there a method to return the address of the symbol you are looking for directly? (I don't really know how things work on Windows. I think the question would be improved by adding the OS and compiler used, since all of this is platform-specific anyway.) – user17732522 Feb 12 '22 at 23:07

1 Answers1

5

If a program performs a computation like:

char x[10],y[10];
int test(ptrdiff_t i)
{
  int *p = x+i;
  *p = 1;
  y[1] = 2;
  return *p;
}

a compiler would be reasonably entitled to assume that because p was formed via pointer arithmetic using x, it could not possible equal y+1, and thus the function would always return 1. If, however, the code had been written as:

char x[10],y[10];
int test(ptrdiff_t i)
{
  int *p = (char*)((uintptr_t)x + i);
  *p = 1;
  y[1] = 2;
  return *p;
}

then such an assumption would be far less reasonable, since unsigned numerical semantics would define the behavior of uintptr_t z = (uintptr_t)(y+1)-(uintptr_t)x as yielding a value such that x+z would equal (uintptr_t)(y+1).

I find the apparent caution clang exhibits here a bit surprising, given that clang is prone to assume that, given some pointer char*p, it's not possible for p to equal y if (uintptr_t)p to equal (uintptr_t)(x+10) and yet for p to equal y. The Standard doesn't forbid such an assumption, but then again it also wouldn't forbid an assumption that code will never use the result of any integer-to-pointer conversion for any purpose other than comparisons with other pointers. Implementations that support type uintptr_t should of course offer stronger guarantees about round-tripped pointers which than merely saying they may be compared for equality with the originals, but the Standard doesn't require such treatment.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Indeed this is correct for straight code. If the address is an access to a memory mapped peripheral, then the warning is not helpful. Here, you never want the compiler to perform optimization on memory mapped hardware registers. You need v13+ to support `NOLINT(xxx)`, accept the noise, or disable the warning. For example, [core_cm4.h](https://github.com/ARM-software/CMSIS_4/blob/f2cad4345783c948ed4a7f5cdb02cdc0856366f1/CMSIS/Include/core_cm4.h#LL1544C31-L1544C46) I did not try to augment with `restrict` to see what happens (and members are volatile). – artless noise Jun 13 '23 at 16:21
  • I'm not sure what "this" is in your comment. There are many situations where the whole purpose of integer-to-pointer casts is to form pointers in ways that are outside the normal semantics associated with C objects, and I doubt that benefits from being able to identify cases where it would be safe to make aliasing assumptions in spite of the presence of integer-to-pointer casts would in most usage scenarios be sufficient to justify the costs of such analysis. – supercat Jun 13 '23 at 17:35
  • *This* is the ability of the compiler to diagnose aliases. Also, I am agreeing with your 2nd points about abnormal semantics. I am just expressing a need for an clang-tidy escape hatch for the abnormal semantics, so the normal objects (which I was calling 'straight code') can be diagnosed. And it seems like we are both saying the same thing; but it was not expressed in the answer. – artless noise Jun 13 '23 at 18:44