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/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,15 +6167,46 @@ 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 && S.LangOpts.OpenCLVersion >= 200) { + // 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. + if (lhQual.getAddressSpace() == LangAS::opencl_constant || + rhQual.getAddressSpace() == LangAS::opencl_constant || + (lhQual.getAddressSpace() != LangAS::opencl_generic && + rhQual.getAddressSpace() != LangAS::opencl_generic)) { + 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, LangAS::opencl_generic)); + LHS = S.ImpCastExprToType( + LHS.get(), incompatTy, + (lhQual.getAddressSpace() != LangAS::opencl_generic) + ? CK_AddressSpaceConversion + : CK_BitCast); + RHS = S.ImpCastExprToType( + RHS.get(), incompatTy, + (rhQual.getAddressSpace() != LangAS::opencl_generic) + ? 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; } 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 i8 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,18 @@ // expected-error@-2{{arithmetic operation with operands of type ('__constant int *' and '__generic int *') which are pointers to non-overlapping address spaces}} #endif + b = var_cmp >= arg_gen; +#ifdef CONSTANT +// expected-error@-2{{comparison between ('__constant int *' and '__generic int *') which are pointers to non-overlapping address spaces}} +#endif + + 0 ? arg_loc : arg_glob; +// expected-error@-1{{conditional operator with the second and third operands of type ('__local int *' and '__global int *') which are pointers to non-overlapping address spaces}} + + 0 ? arg_const : arg_gen; +// expected-error@-1{{conditional operator with the second and third operands of type ('__constant int *' and '__generic int *') which are pointers to non-overlapping address spaces}} + + 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}}