Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5325,7 +5325,9 @@ "composite pointer type %2">, InGroup; def err_typecheck_op_on_nonoverlapping_address_space_pointers : Error< "%select{comparison between %diff{ ($ and $)|}0,1" - "|arithmetic operation with operands of type %diff{ ($ and $)|}0,1}2" + "|arithmetic operation with operands of type %diff{ ($ and $)|}0,1" + "|conditional operator with the second and third operands of type " + "%diff{ ($ and $)|}0,1}2" " which are pointers to non-overlapping address spaces">; def err_typecheck_assign_const : Error< Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -7609,6 +7609,15 @@ Qualifiers LQuals = LHSCan.getLocalQualifiers(); Qualifiers RQuals = RHSCan.getLocalQualifiers(); if (LQuals != RQuals) { + if (getLangOpts().OpenCL && + LHS.getUnqualifiedType() == RHS.getUnqualifiedType() && + LQuals.getCVRQualifiers() == RQuals.getCVRQualifiers()) { + if (LQuals.isAddressSpaceSupersetOf(RQuals)) + return LHS; + if (RQuals.isAddressSpaceSupersetOf(LQuals)) + return RHS; + return QualType(); + } // If any of these qualifiers are different, we have a type // mismatch. if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() || Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -171,7 +171,6 @@ // Don't do this for enums, they can't be redeclared. if (isa(D) || isa(D)) break; - bool Warn = !AA->isInherited(); // Objective-C method declarations in categories are not modelled as // redeclarations, so manually look for a redeclaration in a category @@ -6168,27 +6167,69 @@ QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee); if (CompositeTy.isNull()) { - S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers) - << LHSTy << RHSTy << LHS.get()->getSourceRange() - << RHS.get()->getSourceRange(); // In this situation, we assume void* type. No especially good // reason, but this is what gcc does, and we do have to pick // to get a consistent AST. - QualType incompatTy = S.Context.getPointerType(S.Context.VoidTy); - LHS = S.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast); - RHS = S.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast); + QualType incompatTy; + if (S.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.5 - A pointer to address space A can only be assigned + // to a pointer to the same address space A. Casting a pointer to address + // space A to a pointer to address space B is illegal. + // OpenCL v2.0 s6.5.6 - Clause 6.5.15 Conditional operator, add another + // constraint paragraph: If the second and third operands are pointers + // into different address spaces, the address spaces must overlap. + unsigned ResultAddrSpace; + if (lhQual.isAddressSpaceSupersetOf(rhQual)) { + ResultAddrSpace = lhQual.getAddressSpace(); + } else if (rhQual.isAddressSpaceSupersetOf(lhQual)) { + ResultAddrSpace = rhQual.getAddressSpace(); + } else { + S.Diag(Loc, + diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) + << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + return QualType(); + } + + incompatTy = S.Context.getPointerType( + S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace)); + LHS = S.ImpCastExprToType(LHS.get(), incompatTy, + (lhQual.getAddressSpace() != ResultAddrSpace) + ? CK_AddressSpaceConversion + : CK_BitCast); + RHS = S.ImpCastExprToType(RHS.get(), incompatTy, + (rhQual.getAddressSpace() != ResultAddrSpace) + ? CK_AddressSpaceConversion + : CK_BitCast); + } else { + S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + incompatTy = S.Context.getPointerType(S.Context.VoidTy); + LHS = S.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast); + RHS = S.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast); + } return incompatTy; } // The pointer types are compatible. QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual); + auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast; if (IsBlockPointer) ResultTy = S.Context.getBlockPointerType(ResultTy); - else + else { + auto ResultAddrSpace = ResultTy.getQualifiers().getAddressSpace(); + LHSCastKind = lhQual.getAddressSpace() == ResultAddrSpace + ? CK_BitCast + : CK_AddressSpaceConversion; + RHSCastKind = rhQual.getAddressSpace() == ResultAddrSpace + ? CK_BitCast + : CK_AddressSpaceConversion; ResultTy = S.Context.getPointerType(ResultTy); + } - LHS = S.ImpCastExprToType(LHS.get(), ResultTy, CK_BitCast); - RHS = S.ImpCastExprToType(RHS.get(), ResultTy, CK_BitCast); + LHS = S.ImpCastExprToType(LHS.get(), ResultTy, LHSCastKind); + RHS = S.ImpCastExprToType(RHS.get(), ResultTy, RHSCastKind); return ResultTy; } Index: test/CodeGenOpenCL/address-spaces-conversions.cl =================================================================== --- test/CodeGenOpenCL/address-spaces-conversions.cl +++ test/CodeGenOpenCL/address-spaces-conversions.cl @@ -19,4 +19,6 @@ // CHECK: %{{.*}} = ptrtoint i32 addrspace(1)* %{{.*}} to i64 var_priv = arg_gen > arg_glob; // comparison // CHECK: %{{[0-9]+}} = addrspacecast i32 addrspace(1)* %{{[0-9]+}} to i32 addrspace(4)* + arg_gen = arg_glob ? arg_gen : arg_glob; // conditional operator + // CHECK: %{{[0-9]+}} = addrspacecast i32 addrspace(1)* %{{[0-9]+}} to i32 addrspace(4)* } Index: test/SemaOpenCL/address-spaces-conversions-cl2.0.cl =================================================================== --- test/SemaOpenCL/address-spaces-conversions-cl2.0.cl +++ test/SemaOpenCL/address-spaces-conversions-cl2.0.cl @@ -206,6 +206,38 @@ // expected-error@-2{{arithmetic operation with operands of type ('__constant int *' and '__generic int *') which are pointers to non-overlapping address spaces}} #endif + AS int *var_cond; + arg_gen = 0 ? var_cond : arg_glob; +#ifdef CONSTANT +// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__global int *') which are pointers to non-overlapping address spaces}} +#endif + + arg_gen = 0 ? var_cond : arg_loc; +#ifdef CONSTANT +// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__local int *') which are pointers to non-overlapping address spaces}} +#elif defined(GLOBAL) +// expected-error@-4{{conditional operator with the second and third operands of type ('__global int *' and '__local int *') which are pointers to non-overlapping address spaces}} +#endif + + var_cond = 0 ? var_cond : arg_const; +#ifdef GENERIC +// expected-error@-2{{conditional operator with the second and third operands of type ('__generic int *' and '__constant int *') which are pointers to non-overlapping address spaces}} +#elif defined(GLOBAL) +// expected-error@-4{{conditional operator with the second and third operands of type ('__global int *' and '__constant int *') which are pointers to non-overlapping address spaces}} +#endif + + arg_gen = 0 ? var_cond : arg_priv; +#ifdef CONSTANT +// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and 'int *') which are pointers to non-overlapping address spaces}} +#elif defined(GLOBAL) +// expected-error@-4{{conditional operator with the second and third operands of type ('__global int *' and 'int *') which are pointers to non-overlapping address spaces}} +#endif + + arg_gen = 0 ? var_cond : arg_gen; +#ifdef CONSTANT +// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__generic int *') which are pointers to non-overlapping address spaces}} +#endif + f_glob(var_sub); #ifndef GLOBAL // expected-error-re@-2{{passing '__{{constant|generic}} int *' to parameter of type '__global int *' changes address space of pointer}}