summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaxun Liu <Yaxun.Liu@amd.com>2018-07-20 11:32:51 +0000
committerYaxun Liu <Yaxun.Liu@amd.com>2018-07-20 11:32:51 +0000
commit0bb7730cf5a4fff5ff9caad7d38bc7ca193aa9c4 (patch)
tree114a1607db63966c291555ab5efcd0e10e4d7c9a
parent1a8f8375fb2268e94c72dbc26c55992702d8ca6c (diff)
downloadclang-0bb7730cf5a4fff5ff9caad7d38bc7ca193aa9c4.tar.gz
Sema: Fix explicit address space cast in C++
Currently clang does not allow implicit cast of a pointer to a pointer type in different address space but allows C-style cast of a pointer to a pointer type in different address space. However, there is a bug in Sema causing incorrect Cast Expr in AST for the latter case, which in turn results in invalid LLVM IR in codegen. This is because Sema::IsQualificationConversion returns true for a cast of pointer to a pointer type in different address space, which in turn allows a standard conversion and results in a cast expression with no op in AST. This patch fixes that by let Sema::IsQualificationConversion returns false for a cast of pointer to a pointer type in different address space, which in turn disallows standard conversion, implicit cast, and static cast. Finally it results in an reinterpret cast and correct conversion kind is set. Differential Revision: https://reviews.llvm.org/D49294 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337540 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaCast.cpp8
-rw-r--r--lib/Sema/SemaOverload.cpp9
-rw-r--r--test/CodeGenCXX/address-space-cast.cpp15
3 files changed, 32 insertions, 0 deletions
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index 86633d6dd5..b3f6be4aec 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -1955,6 +1955,12 @@ 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,
@@ -2198,6 +2204,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
} else {
Kind = CK_BitCast;
}
+ } else if (IsAddressSpaceConversion(SrcType, DestType)) {
+ Kind = CK_AddressSpaceConversion;
} else {
Kind = CK_BitCast;
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 822c3c0c6b..390782b35e 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -3150,6 +3150,15 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
= PreviousToQualsIncludeConst && ToQuals.hasConst();
}
+ // Allows address space promotion by language rules implemented in
+ // Type::Qualifiers::isAddressSpaceSupersetOf.
+ Qualifiers FromQuals = FromType.getQualifiers();
+ Qualifiers ToQuals = ToType.getQualifiers();
+ if (!ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
+ !FromQuals.isAddressSpaceSupersetOf(ToQuals)) {
+ return false;
+ }
+
// We are left with FromType and ToType being the pointee types
// after unwrapping the original FromType and ToType the same number
// of types. If we unwrapped any pointers, and if FromType and
diff --git a/test/CodeGenCXX/address-space-cast.cpp b/test/CodeGenCXX/address-space-cast.cpp
new file mode 100644
index 0000000000..334a1a63e6
--- /dev/null
+++ b/test/CodeGenCXX/address-space-cast.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s
+
+#define __private__ __attribute__((address_space(5)))
+
+void func_pchar(__private__ char *x);
+
+void test_cast(char *gen_ptr) {
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+ __private__ char *priv_ptr = (__private__ char *)gen_ptr;
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]])
+ func_pchar((__private__ char *)gen_ptr);
+}