1.. title:: clang-tidy - performance-no-int-to-ptr
2
3performance-no-int-to-ptr
4=========================
5
6Diagnoses every integer to pointer cast.
7
8While casting an (integral) pointer to an integer is obvious - you just get
9the integral value of the pointer, casting an integer to an (integral) pointer
10is deceivingly different. While you will get a pointer with that integral value,
11if you got that integral value via a pointer-to-integer cast originally,
12the new pointer will lack the provenance information from the original pointer.
13
14So while (integral) pointer to integer casts are effectively no-ops,
15and are transparent to the optimizer, integer to (integral) pointer casts
16are *NOT* transparent, and may conceal information from optimizer.
17
18While that may be the intention, it is not always so. For example,
19let's take a look at a routine to align the pointer up to the multiple of 16:
20The obvious, naive implementation for that is:
21
22.. code-block:: c++
23
24  char* src(char* maybe_underbiased_ptr) {
25    uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr;
26    uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15;
27    uintptr_t aligned_intptr = aligned_biased_intptr & (~15);
28    return (char*)aligned_intptr; // warning: avoid integer to pointer casts [performance-no-int-to-ptr]
29  }
30
31The check will rightfully diagnose that cast.
32
33But when provenance concealment is not the goal of the code, but an accident,
34this example can be rewritten as follows, without using integer to pointer cast:
35
36.. code-block:: c++
37
38  char*
39  tgt(char* maybe_underbiased_ptr) {
40      uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr;
41      uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15;
42      uintptr_t aligned_intptr = aligned_biased_intptr & (~15);
43      uintptr_t bias = aligned_intptr - maybe_underbiased_intptr;
44      return maybe_underbiased_ptr + bias;
45  }
46