From 69a2c924b9e825616c62c7985c81410b14657d5c Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Mon, 2 May 2011 18:21:19 +0000 Subject: Add a warning for when reinterpret_cast leads to undefined behavior, patch by Richard Trieu! llvm-svn: 130703 --- clang/test/SemaCXX/reinterpret-cast.cpp | 154 +++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 1 deletion(-) (limited to 'clang/test') diff --git a/clang/test/SemaCXX/reinterpret-cast.cpp b/clang/test/SemaCXX/reinterpret-cast.cpp index f5262496c4b..449fecb1607 100644 --- a/clang/test/SemaCXX/reinterpret-cast.cpp +++ b/clang/test/SemaCXX/reinterpret-cast.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding %s +// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding -Wundefined-reinterpret-cast %s #include @@ -116,3 +116,155 @@ namespace PR9564 { __attribute((ext_vector_type(4))) typedef float v4; float& w(v4 &a) { return reinterpret_cast(a[1]); } // expected-error {{not allowed}} } + +void dereference_reinterpret_cast() { + struct A {}; + class B {}; + A a; + B b; + long l; + double d; + float f; + char c; + unsigned char uc; + void* v_ptr; + (void)reinterpret_cast(l); // expected-warning {{reinterpret_cast from 'long' to 'double &' has undefined behavior}} + (void)*reinterpret_cast(&l); // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'long *' has undefined behavior}} + (void)reinterpret_cast(f); // expected-warning {{reinterpret_cast from 'float' to 'double &' has undefined behavior}} + (void)*reinterpret_cast(&f); // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'float *' has undefined behavior}} + (void)reinterpret_cast(l); // expected-warning {{reinterpret_cast from 'long' to 'float &' has undefined behavior}} + (void)*reinterpret_cast(&l); // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'long *' has undefined behavior}} + (void)reinterpret_cast(d); // expected-warning {{reinterpret_cast from 'double' to 'float &' has undefined behavior}} + (void)*reinterpret_cast(&d); // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'double *' has undefined behavior}} + + // TODO: add warning for tag types + (void)reinterpret_cast(b); + (void)*reinterpret_cast(&b); + (void)reinterpret_cast(a); + (void)*reinterpret_cast(&a); + + // Casting to itself is allowed + (void)reinterpret_cast(a); + (void)*reinterpret_cast(&a); + (void)reinterpret_cast(b); + (void)*reinterpret_cast(&b); + (void)reinterpret_cast(l); + (void)*reinterpret_cast(&l); + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(c); + (void)*reinterpret_cast(&c); + + // Casting to and from chars are allowable + (void)reinterpret_cast(c); + (void)*reinterpret_cast(&c); + (void)reinterpret_cast(c); + (void)*reinterpret_cast(&c); + (void)reinterpret_cast(c); + (void)*reinterpret_cast(&c); + (void)reinterpret_cast(c); + (void)*reinterpret_cast(&c); + (void)reinterpret_cast(l); + (void)*reinterpret_cast(&l); + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(f); + (void)*reinterpret_cast(&f); + + // Casting from void pointer. + (void)*reinterpret_cast(v_ptr); + (void)*reinterpret_cast(v_ptr); + (void)*reinterpret_cast(v_ptr); + (void)*reinterpret_cast(v_ptr); + (void)*reinterpret_cast(v_ptr); + + // Casting to void pointer + (void)*reinterpret_cast(&a); + (void)*reinterpret_cast(&b); + (void)*reinterpret_cast(&l); + (void)*reinterpret_cast(&d); + (void)*reinterpret_cast(&f); +} + +void reinterpret_cast_whitelist () { + // the dynamic type of the object + int a; + float b; + (void)reinterpret_cast(a); + (void)*reinterpret_cast(&a); + (void)reinterpret_cast(b); + (void)*reinterpret_cast(&b); + + // a cv-qualified version of the dynamic object + (void)reinterpret_cast(a); + (void)*reinterpret_cast(&a); + (void)reinterpret_cast(a); + (void)*reinterpret_cast(&a); + (void)reinterpret_cast(a); + (void)*reinterpret_cast(&a); + (void)reinterpret_cast(b); + (void)*reinterpret_cast(&b); + (void)reinterpret_cast(b); + (void)*reinterpret_cast(&b); + (void)reinterpret_cast(b); + (void)*reinterpret_cast(&b); + + // a type that is the signed or unsigned type corresponding to the dynamic + // type of the object + signed d; + unsigned e; + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(e); + (void)*reinterpret_cast(&e); + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(e); + (void)*reinterpret_cast(&e); + + // a type that is the signed or unsigned type corresponding a cv-qualified + // version of the dynamic type the object + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(e); + (void)*reinterpret_cast(&e); + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(e); + (void)*reinterpret_cast(&e); + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(e); + (void)*reinterpret_cast(&e); + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(e); + (void)*reinterpret_cast(&e); + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(e); + (void)*reinterpret_cast(&e); + (void)reinterpret_cast(d); + (void)*reinterpret_cast(&d); + (void)reinterpret_cast(e); + (void)*reinterpret_cast(&e); + + // an aggregate or union type that includes one of the aforementioned types + // among its members (including, recursively, a member of a subaggregate or + // contained union) + // TODO: checking is not implemented for tag types + + // a type that is a (possible cv-qualified) base class type of the dynamic + // type of the object + // TODO: checking is not implemented for tag types + + // a char or unsigned char type + (void)reinterpret_cast(a); + (void)*reinterpret_cast(&a); + (void)reinterpret_cast(a); + (void)*reinterpret_cast(&a); + (void)reinterpret_cast(b); + (void)*reinterpret_cast(&b); + (void)reinterpret_cast(b); + (void)*reinterpret_cast(&b); +} -- cgit v1.2.3