46 lines
1.9 KiB
ReStructuredText
46 lines
1.9 KiB
ReStructuredText
|
.. title:: clang-tidy - performance-no-int-to-ptr
|
||
|
|
||
|
performance-no-int-to-ptr
|
||
|
=========================
|
||
|
|
||
|
Diagnoses every integer to pointer cast.
|
||
|
|
||
|
While casting an (integral) pointer to an integer is obvious - you just get
|
||
|
the integral value of the pointer, casting an integer to an (integral) pointer
|
||
|
is deceivingly different. While you will get a pointer with that integral value,
|
||
|
if you got that integral value via a pointer-to-integer cast originally,
|
||
|
the new pointer will lack the provenance information from the original pointer.
|
||
|
|
||
|
So while (integral) pointer to integer casts are effectively no-ops,
|
||
|
and are transparent to the optimizer, integer to (integral) pointer casts
|
||
|
are *NOT* transparent, and may conceal information from optimizer.
|
||
|
|
||
|
While that may be the intention, it is not always so. For example,
|
||
|
let's take a look at a routine to align the pointer up to the multiple of 16:
|
||
|
The obvious, naive implementation for that is:
|
||
|
|
||
|
.. code-block:: c++
|
||
|
|
||
|
char* src(char* maybe_underbiased_ptr) {
|
||
|
uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr;
|
||
|
uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15;
|
||
|
uintptr_t aligned_intptr = aligned_biased_intptr & (~15);
|
||
|
return (char*)aligned_intptr; // warning: avoid integer to pointer casts [performance-no-int-to-ptr]
|
||
|
}
|
||
|
|
||
|
The check will rightfully diagnose that cast.
|
||
|
|
||
|
But when provenance concealment is not the goal of the code, but an accident,
|
||
|
this example can be rewritten as follows, without using integer to pointer cast:
|
||
|
|
||
|
.. code-block:: c++
|
||
|
|
||
|
char*
|
||
|
tgt(char* maybe_underbiased_ptr) {
|
||
|
uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr;
|
||
|
uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15;
|
||
|
uintptr_t aligned_intptr = aligned_biased_intptr & (~15);
|
||
|
uintptr_t bias = aligned_intptr - maybe_underbiased_intptr;
|
||
|
return maybe_underbiased_ptr + bias;
|
||
|
}
|