Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -7659,6 +7659,12 @@ } } } +/// Helper function for adjusting address spaces for the pointer or reference +/// operands of builtin operators depending on the argument. +static QualType AdjustAddressSpaceForBuiltinOperandType(Sema &S, QualType T, + Expr *Arg) { + return S.Context.getAddrSpaceQualType(T, Arg->getType().getAddressSpace()); +} /// Helper function for AddBuiltinOperatorCandidates() that adds /// the volatile- and non-volatile-qualified assignment operators for the @@ -7670,15 +7676,17 @@ QualType ParamTypes[2]; // T& operator=(T&, T) - ParamTypes[0] = S.Context.getLValueReferenceType(T); + ParamTypes[0] = S.Context.getLValueReferenceType( + AdjustAddressSpaceForBuiltinOperandType(S, T, Args[0])); ParamTypes[1] = T; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); if (!S.Context.getCanonicalType(T).isVolatileQualified()) { // volatile T& operator=(volatile T&, T) - ParamTypes[0] - = S.Context.getLValueReferenceType(S.Context.getVolatileType(T)); + ParamTypes[0] = S.Context.getLValueReferenceType( + AdjustAddressSpaceForBuiltinOperandType(S, S.Context.getVolatileType(T), + Args[0])); ParamTypes[1] = T; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); @@ -8573,8 +8581,9 @@ ParamTypes[1] = ArithmeticTypes[Right]; // Add this built-in operator as a candidate (VQ is empty). - ParamTypes[0] = - S.Context.getLValueReferenceType(ArithmeticTypes[Left]); + ParamTypes[0] = S.Context.getLValueReferenceType( + AdjustAddressSpaceForBuiltinOperandType(S, ArithmeticTypes[Left], + Args[0])); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); if (VisibleTypeConversionsQuals.hasVolatile()) { // Add this built-in operator as a candidate (VQ is 'volatile'). Index: test/CodeGenOpenCLCXX/addrspace-operators.cl =================================================================== --- test/CodeGenOpenCLCXX/addrspace-operators.cl +++ test/CodeGenOpenCLCXX/addrspace-operators.cl @@ -0,0 +1,46 @@ +//RUN: %clang_cc1 %s -triple spir -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s + +enum E { + a, + b, +}; + +class C { +public: + void Assign(E e) { me = e; } + void OrAssign(E e) { mi |= e; } + E me; + int mi; +}; + +__global E globE; +//CHECK-LABEL: define spir_func void @_Z3barv() +void bar() { + C c; + //CHECK: addrspacecast %class.C* %c to %class.C addrspace(4)* + //CHECK: call void @_ZNU3AS41C6AssignE1E(%class.C addrspace(4)* %{{[0-9]+}}, i32 0) + c.Assign(a); + //CHECK: addrspacecast %class.C* %c to %class.C addrspace(4)* + //CHECK: call void @_ZNU3AS41C8OrAssignE1E(%class.C addrspace(4)* %{{[0-9]+}}, i32 0) + c.OrAssign(a); + + E e; + // CHECK: store i32 1, i32* %e + e = b; + // CHECK: store i32 0, i32 addrspace(1)* @globE + globE = a; + // FIXME: Sema fails here because it thinks the types are incompatible. + //e = b; + //globE = a; +} + +//CHECK: define linkonce_odr void @_ZNU3AS41C6AssignE1E(%class.C addrspace(4)* %this, i32 %e) +//CHECK: [[E:%[0-9]+]] = load i32, i32* %e.addr +//CHECK: %me = getelementptr inbounds %class.C, %class.C addrspace(4)* %this1, i32 0, i32 0 +//CHECK: store i32 [[E]], i32 addrspace(4)* %me + +//CHECK define linkonce_odr void @_ZNU3AS41C8OrAssignE1E(%class.C addrspace(4)* %this, i32 %e) +//CHECK: [[E:%[0-9]+]] = load i32, i32* %e.addr +//CHECK: %mi = getelementptr inbounds %class.C, %class.C addrspace(4)* %this1, i32 0, i32 1 +//CHECK: [[MI:%[0-9]+]] = load i32, i32 addrspace(4)* %mi +//CHECK: %or = or i32 [[MI]], [[E]]