Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -1606,12 +1606,21 @@ goto CheckNoBasePath; case CK_AddressSpaceConversion: - assert(getType()->isPointerType() || getType()->isBlockPointerType()); - assert(getSubExpr()->getType()->isPointerType() || - getSubExpr()->getType()->isBlockPointerType()); - assert(getType()->getPointeeType().getAddressSpace() != - getSubExpr()->getType()->getPointeeType().getAddressSpace()); - LLVM_FALLTHROUGH; + assert(/*If pointer type then addr spaces for pointees must differ*/ + (((getType()->isPointerType() && + getSubExpr()->getType()->isPointerType()) || + (getType()->isBlockPointerType() && + getSubExpr()->getType()->isBlockPointerType())) && + getType()->getPointeeType().getAddressSpace() != + getSubExpr()->getType()->getPointeeType().getAddressSpace()) || + /*For non pointer type, addr spaces of type must differ*/ + (!getType()->isPointerType() && + !getSubExpr()->getType()->isPointerType() && + !getType()->isBlockPointerType() && + !getSubExpr()->getType()->isBlockPointerType() && + (getType().getAddressSpace() != + getSubExpr()->getType().getAddressSpace()))); + goto CheckNoBasePath; // These should not have an inheritance path. case CK_Dynamic: case CK_ToUnion: Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -4151,7 +4151,6 @@ case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: - case CK_AddressSpaceConversion: case CK_IntToOCLSampler: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); @@ -4246,6 +4245,15 @@ return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(), CGM.getTBAAInfoForSubobject(LV, E->getType())); } + case CK_AddressSpaceConversion: { + LValue LV = EmitLValue(E->getSubExpr()); + QualType DestTy = getContext().getPointerType(E->getType()); + Address V = + Builder.CreateAddrSpaceCast(LV.getAddress(), ConvertType(DestTy)); + + return MakeAddrLValue(V, DestTy, LV.getBaseInfo(), + CGM.getTBAAInfoForSubobject(LV, DestTy)); + } case CK_ObjCObjectLValueCast: { LValue LV = EmitLValue(E->getSubExpr()); Address V = Builder.CreateElementBitCast(LV.getAddress(), Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -572,8 +572,9 @@ case SCS_extern: case SCS_private_extern: case SCS_static: - if (S.getLangOpts().OpenCLVersion < 120) { - DiagID = diag::err_opencl_unknown_type_specifier; + if (S.getLangOpts().OpenCLVersion < 120 && + !S.getLangOpts().OpenCLCPlusPlus) { + DiagID = diag::err_opencl_unknown_type_specifier; PrevSpec = getSpecifierName(SC); return true; } Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -7362,9 +7362,10 @@ if (!T->isSamplerT() && !(T.getAddressSpace() == LangAS::opencl_constant || (T.getAddressSpace() == LangAS::opencl_global && - getLangOpts().OpenCLVersion == 200))) { + (getLangOpts().OpenCLVersion == 200 || + getLangOpts().OpenCLCPlusPlus)))) { int Scope = NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1; - if (getLangOpts().OpenCLVersion == 200) + if (getLangOpts().OpenCLVersion == 200 || getLangOpts().OpenCLCPlusPlus) Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) << Scope << "global or constant"; else Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -4276,10 +4276,17 @@ case ICK_Qualification: { // The qualification keeps the category of the inner expression, unless the // target type isn't a reference. - ExprValueKind VK = ToType->isReferenceType() ? - From->getValueKind() : VK_RValue; - From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), - CK_NoOp, VK, /*BasePath=*/nullptr, CCK).get(); + ExprValueKind VK = + ToType->isReferenceType() ? From->getValueKind() : VK_RValue; + + CastKind CK = (ToType->getPointeeType().getAddressSpace() != + From->getType()->getPointeeType().getAddressSpace()) + ? CK_AddressSpaceConversion + : CK_NoOp; + + From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), CK, VK, + /*BasePath=*/nullptr, CCK) + .get(); if (SCS.DeprecatedStringLiteralToCharPtr && !getLangOpts().WritableStrings) { Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -7603,12 +7603,15 @@ case SK_QualificationConversionRValue: { // Perform a qualification conversion; these can never go wrong. ExprValueKind VK = - Step->Kind == SK_QualificationConversionLValue ? - VK_LValue : - (Step->Kind == SK_QualificationConversionXValue ? - VK_XValue : - VK_RValue); - CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK); + Step->Kind == SK_QualificationConversionLValue + ? VK_LValue + : (Step->Kind == SK_QualificationConversionXValue ? VK_XValue + : VK_RValue); + CastKind CK = (Step->Type.getAddressSpace() != + CurInit.get()->getType().getAddressSpace()) + ? CK_AddressSpaceConversion + : CK_NoOp; + CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK, VK); break; } Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -7177,7 +7177,8 @@ bool IsPointee = ChunkIndex > 0 && (D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer || - D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer); + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer || + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Reference); bool IsFuncReturnType = ChunkIndex > 0 && D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function; Index: test/CodeGenOpenCLCXX/address-space-deduction.cl =================================================================== --- /dev/null +++ test/CodeGenOpenCLCXX/address-space-deduction.cl @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - | FileCheck %s -check-prefixes=COMMON,PTR +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - -DREF | FileCheck %s -check-prefixes=COMMON,REF + +#ifdef REF +#define PTR & +#define ADR(x) x +#else +#define PTR * +#define ADR(x) &x +#endif + +//COMMON: @glob = addrspace(1) global i32 +int glob; +//PTR: @glob_p = addrspace(1) global i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @glob to i32 addrspace(4)*) +//REF: @glob_p = addrspace(1) global i32 addrspace(4)* null +int PTR glob_p = ADR(glob); + +//COMMON: @_ZZ3fooi{{P|R}}U3AS4iE6loc_st = internal addrspace(1) global i32 +//PTR: @_ZZ3fooiPU3AS4iE8loc_st_p = internal addrspace(1) global i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @_ZZ3fooiPU3AS4iE6loc_st to i32 addrspace(4)*) +//REF: @_ZZ3fooiRU3AS4iE8loc_st_p = internal addrspace(1) global i32 addrspace(4)* null +//COMMON: @loc_ext_p = external addrspace(1) {{global|constant}} i32 addrspace(4)* +//COMMON: @loc_ext = external addrspace(1) global i32 + +//REF: store i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @glob to i32 addrspace(4)*), i32 addrspace(4)* addrspace(1)* @glob_p + +//COMMON: define spir_func i32 @_Z3fooi{{P|R}}U3AS4i(i32 %par, i32 addrspace(4)*{{.*}} %par_p) +int foo(int par, int PTR par_p){ +//COMMON: %loc = alloca i32 + int loc; +//COMMON: %loc_p = alloca i32 addrspace(4)* +//COMMON: [[GAS:%[0-9]+]] = addrspacecast i32* %loc to i32 addrspace(4)* +//COMMON: store i32 addrspace(4)* [[GAS]], i32 addrspace(4)** %loc_p + int PTR loc_p = ADR(loc); + +// CHECK directives for the following code are located above. + static int loc_st; + static int PTR loc_st_p = ADR(loc_st); + extern int loc_ext; + extern int PTR loc_ext_p; + (void)loc_ext_p; + return loc_ext; +}