Created
June 23, 2024 20:48
-
-
Save matu3ba/f9088fdaf0d1eaecc07dec21133e5433 to your computer and use it in GitHub Desktop.
cerberus error ptrtoint_inttoptr.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cerberus ptrtoint_inttoptr.c | |
ptrtoint_inttoptr.c:24:16: error: constraint violation: initializing 'void*' with an expression of incompatible type 'usual arithmetic conversions with type [integer promotion of [usual arithmetic conversions with type [integer promotion of [uintptr_t] and integer promotion of [unsigned short]]] and integer promotion of [integer promotion of [uintptr_t]]]' | |
void * ptr = ((uintptr_t)mem+align_min_1) & ~(uintptr_t)align_min_1; | |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
§6.7.9#11, sentence 2: | |
11 The initializer for a scalar shall be a single expression, optionally enclosed in braces. The | |
initial value of the object is that of the expression (after conversion); the same type | |
constraints and conversions as for simple assignment apply, taking the type of the scalar | |
to be the unqualified version of its declared type. | |
§6.5.16.1#1: | |
1 One of the following shall hold:112) | |
-- the left operand has atomic, qualified, or unqualified arithmetic type, and the right has | |
arithmetic type; | |
-- the left operand has an atomic, qualified, or unqualified version of a structure or union | |
type compatible with the type of the right; | |
-- the left operand has atomic, qualified, or unqualified pointer type, and (considering | |
the type the left operand would have after lvalue conversion) both operands are | |
pointers to qualified or unqualified versions of compatible types, and the type pointed | |
to by the left has all the qualifiers of the type pointed to by the right; | |
-- the left operand has atomic, qualified, or unqualified pointer type, and (considering | |
the type the left operand would have after lvalue conversion) one operand is a pointer | |
to an object type, and the other is a pointer to a qualified or unqualified version of | |
void, and the type pointed to by the left has all the qualifiers of the type pointed to | |
by the right; | |
-- the left operand is an atomic, qualified, or unqualified pointer, and the right is a null | |
pointer constant; or | |
-- the left operand has type atomic, qualified, or unqualified _Bool, and the right is a | |
pointer. | |
FOOTNOTE.112: | |
The asymmetric appearance of these constraints with respect to type qualifiers is due to the conversion | |
(specified in 6.3.2.1) that changes lvalues to ``the value of the expression'' and thus removes any type | |
qualifiers that were applied to the type category of the expression (for example, it removes const but | |
not volatile from the type int volatile * const). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <inttypes.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
static void memset_16aligned(void * ptr, char byte, size_t size_bytes, uint16_t alignment) { | |
assert((size_bytes & (alignment-1)) == 0); // Size aligned | |
assert(((uintptr_t)ptr & (alignment-1)) == 0); // Pointer aligned | |
memset(ptr, byte, size_bytes); | |
} | |
// 1. Careful with segmented address spaces: lookup uintptr_t semantics | |
// 2. Careful with long standing existing optimization compiler bugs pointer to | |
// integer and back optimizations in for example clang and gcc | |
// 3. Careful with LTO potentially creating problem 2. | |
// 4. Consider C11 aligned_alloc or posix_memalign | |
void ptrtointtoptr() { | |
const uint16_t alignment = 16; | |
const uint16_t align_min_1 = alignment - 1; | |
void * mem = malloc(1024+align_min_1); | |
// C89: void *ptr = (void *)(((INT_WITH_PTR_SIZE)mem+align_min_1) & ~(INT_WITH_PTR_SIZE)align_min_1); | |
// ie void *ptr = (void *)(((uint64_t)mem+align_min_1) & ~(uint64_t)align_min_1); | |
// offset ptr to next alignment byte boundary | |
// void * ptr = (void *)(((uintptr_t)mem+align_min_1) & ~(uintptr_t)align_min_1); | |
void * ptr = ((uintptr_t)mem+align_min_1) & ~(uintptr_t)align_min_1; | |
printf("0x%08" PRIXPTR ", 0x%08" PRIXPTR "\n", (uintptr_t)mem, (uintptr_t)ptr); | |
memset_16aligned(ptr, 0, 1024, alignment); | |
free(mem); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment