Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -394,6 +394,14 @@ if (ExprTy == TypeTy) return E; + // In the event an address space cast is requested, the kind passed from the + // caller should not be CK_NoOp. + assert((Kind != CK_NoOp || + !(ExprTy->isPointerType() && TypeTy->isPointerType() && + ExprTy->getPointeeType().getAddressSpace() != + TypeTy->getPointeeType().getAddressSpace())) && + "NoOp is not a valid kind for and address cast"); + if (ImplicitCastExpr *ImpCast = dyn_cast(E)) { if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { ImpCast->setType(Ty); Index: lib/Sema/SemaCast.cpp =================================================================== --- lib/Sema/SemaCast.cpp +++ lib/Sema/SemaCast.cpp @@ -2040,7 +2040,7 @@ << OpRange; return TC_Success; } - + // C++ 5.2.10p7: A pointer to an object can be explicitly converted to // a pointer to an object of different type. // Void pointers are not specified, but supported by every compiler out there. @@ -2108,6 +2108,22 @@ return; } + // If we are casting pointers, we need to check whether this refers to an + // address space cast. + if (DestType->isPointerType() && SrcExpr.get()->getType()->isPointerType()) { + QualType DTy = + Self.getASTContext().getCanonicalType(DestType->getPointeeType()); + QualType STy = Self.getASTContext().getCanonicalType( + SrcExpr.get()->getType()->getPointeeType()); + // If the pointer point to the same type in different address spaces, this + // is an address-space cast. + if (STy.getTypePtr() == DTy.getTypePtr() && + STy.getAddressSpace() != DTy.getAddressSpace()) { + Kind = CK_AddressSpaceConversion; + return; + } + } + // C++ [expr.cast]p5: The conversions performed by // - a const_cast, // - a static_cast, Index: test/CodeGen/address-space-explicit-cast.c =================================================================== --- /dev/null +++ test/CodeGen/address-space-explicit-cast.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -emit-llvm -o - -x c %s | FileCheck -check-prefix=CHECK %s +// RUN: %clang_cc1 -emit-llvm -o - -x c++ %s | FileCheck -check-prefix=CHECK-CXX %s + +typedef __attribute__((address_space(1))) char *AddrSpaceCharType; + +// CHECK-LABEL: @foo() +// CHECK-CXX-LABEL: @_Z3foov() +void foo() { + // CHECK: %p = alloca i8 addrspace(1)* + // CHECK-CXX: %p = alloca i8 addrspace(1)* + AddrSpaceCharType p; + + // CHECK: store i8 addrspace(1)* addrspacecast ({{.*}} to i8 addrspace(1)*), i8 addrspace(1)** %p + // CHECK-CXX: store i8 addrspace(1)* addrspacecast ({{.*}} to i8 addrspace(1)*), i8 addrspace(1)** %p + p = (AddrSpaceCharType) "a"; +}