Since pointer overflow is undefined behavior in C, some compilers such
as clang optimize away the check !((ptr) + 1) in the macro IS_NIL().
This patch fixes the issue by casting the pointer type to uintptr_t,
the operations of which are well-defined.
Signed-off-by: Xi Wang <xi@mit.edu>
---
Try the simplified code below.
#define IS_NIL(ptr) (!((ptr) + 1))
void bar(void);
void foo(char *p)
{
if (p) {
if (IS_NIL(p))
bar();
}
}
$ clang -S -o - t.c -O2
foo: # @foo
.cfi_startproc
# BB#0: # %entry
ret
.Ltmp0:
.size foo, .Ltmp0-foo
.cfi_endproc
Clearly, clang optimizes away the check.
---
xen/include/asm-x86/mm.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index fd9d654..8f0f78a 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -574,7 +574,7 @@ int donate_page(
int map_ldt_shadow_page(unsigned int);
#define NIL(type) ((type *)NULL - 1)
-#define IS_NIL(ptr) (!((ptr) + 1))
+#define IS_NIL(ptr) (!((uintptr_t)(ptr) + sizeof(*(ptr))))
int create_perdomain_mapping(struct domain *, unsigned long va,
unsigned int nr, l1_pgentry_t **,
--
1.7.10.4