Sema: Fix explicit address space cast involving void pointers
authorYaxun Liu <Yaxun.Liu@amd.com>
Fri, 3 Aug 2018 03:18:56 +0000 (03:18 +0000)
committerYaxun Liu <Yaxun.Liu@amd.com>
Fri, 3 Aug 2018 03:18:56 +0000 (03:18 +0000)
Explicit cast of a void pointer to a pointer type in different address space is
incorrectly classified as bitcast, which causes invalid bitcast in codegen.

The patch fixes that by checking the address space of the source and destination
type and set the correct cast kind.

Differential Revision: https://reviews.llvm.org/D50003

llvm-svn: 338805

clang/lib/Sema/SemaCast.cpp
clang/test/CodeGenCXX/address-space-cast.cpp

index 57aac80..8599fe0 100644 (file)
@@ -1044,6 +1044,17 @@ void CastOperation::CheckStaticCast() {
   }
 }
 
+static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) {
+  auto *SrcPtrType = SrcType->getAs<PointerType>();
+  if (!SrcPtrType)
+    return false;
+  auto *DestPtrType = DestType->getAs<PointerType>();
+  if (!DestPtrType)
+    return false;
+  return SrcPtrType->getPointeeType().getAddressSpace() !=
+         DestPtrType->getPointeeType().getAddressSpace();
+}
+
 /// TryStaticCast - Check if a static cast can be performed, and do so if
 /// possible. If @p CStyle, ignore access restrictions on hierarchy casting
 /// and casting away constness.
@@ -1185,7 +1196,9 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
               return TC_Failed;
             }
           }
-          Kind = CK_BitCast;
+          Kind = IsAddressSpaceConversion(SrcType, DestType)
+                     ? CK_AddressSpaceConversion
+                     : CK_BitCast;
           return TC_Success;
         }
 
@@ -1964,12 +1977,6 @@ static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType,
   return Result.isUsable();
 }
 
-static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) {
-  return SrcType->isPointerType() && DestType->isPointerType() &&
-         SrcType->getAs<PointerType>()->getPointeeType().getAddressSpace() !=
-             DestType->getAs<PointerType>()->getPointeeType().getAddressSpace();
-}
-
 static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
                                         QualType DestType, bool CStyle,
                                         SourceRange OpRange,
index 334a1a6..e0cf3c1 100644 (file)
@@ -3,13 +3,63 @@
 #define __private__ __attribute__((address_space(5)))
 
 void func_pchar(__private__ char *x);
+void func_pvoid(__private__ void *x);
+void func_pint(__private__ int *x);
 
-void test_cast(char *gen_ptr) {
+void test_cast(char *gen_char_ptr, void *gen_void_ptr, int *gen_int_ptr) {
   // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
   // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
-  __private__ char *priv_ptr = (__private__ char *)gen_ptr;
+  __private__ char *priv_char_ptr = (__private__ char *)gen_char_ptr;
 
   // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+  priv_char_ptr = (__private__ char *)gen_void_ptr;
+
+  // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+  priv_char_ptr = (__private__ char *)gen_int_ptr;
+
+  // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+  __private__ void *priv_void_ptr = (__private__ void *)gen_char_ptr;
+
+  // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+  priv_void_ptr = (__private__ void *)gen_void_ptr;
+
+  // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+  priv_void_ptr = (__private__ void *)gen_int_ptr;
+
+  // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i32 addrspace(5)*
+  // CHECK-NEXT: store i32 addrspace(5)* %[[cast]]
+  __private__ int *priv_int_ptr = (__private__ int *)gen_void_ptr;
+
+  // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]])
+  func_pchar((__private__ char *)gen_char_ptr);
+
+  // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]])
+  func_pchar((__private__ char *)gen_void_ptr);
+
+  // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)*
   // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]])
-  func_pchar((__private__ char *)gen_ptr);
+  func_pchar((__private__ char *)gen_int_ptr);
+
+  // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: call void @_Z10func_pvoidPU3AS5v(i8 addrspace(5)* %[[cast]])
+  func_pvoid((__private__ void *)gen_char_ptr);
+
+  // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: call void @_Z10func_pvoidPU3AS5v(i8 addrspace(5)* %[[cast]])
+  func_pvoid((__private__ void *)gen_void_ptr);
+
+  // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)*
+  // CHECK-NEXT: call void @_Z10func_pvoidPU3AS5v(i8 addrspace(5)* %[[cast]])
+  func_pvoid((__private__ void *)gen_int_ptr);
+
+  // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i32 addrspace(5)*
+  // CHECK-NEXT: call void @_Z9func_pintPU3AS5i(i32 addrspace(5)* %[[cast]])
+  func_pint((__private__ int *)gen_void_ptr);
 }