From: Yaxun Liu Date: Fri, 3 Aug 2018 03:18:56 +0000 (+0000) Subject: Sema: Fix explicit address space cast involving void pointers X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d3ee85bfddb61cc7d77488784eef1515bcc68a9d;p=clang Sema: Fix explicit address space cast involving void pointers 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338805 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 57aac80f5a..8599fe09a5 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -1044,6 +1044,17 @@ void CastOperation::CheckStaticCast() { } } +static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) { + auto *SrcPtrType = SrcType->getAs(); + if (!SrcPtrType) + return false; + auto *DestPtrType = DestType->getAs(); + 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()->getPointeeType().getAddressSpace() != - DestType->getAs()->getPointeeType().getAddressSpace(); -} - static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, SourceRange OpRange, diff --git a/test/CodeGenCXX/address-space-cast.cpp b/test/CodeGenCXX/address-space-cast.cpp index 334a1a63e6..e0cf3c199b 100644 --- a/test/CodeGenCXX/address-space-cast.cpp +++ b/test/CodeGenCXX/address-space-cast.cpp @@ -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); }