Index: cfe/trunk/include/clang/AST/Type.h =================================================================== --- cfe/trunk/include/clang/AST/Type.h +++ cfe/trunk/include/clang/AST/Type.h @@ -460,21 +460,25 @@ Mask |= qs.Mask; } - /// Returns true if this address space is a superset of the other one. + /// Returns true if address space A is equal to or a superset of B. /// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of /// overlapping address spaces. /// CL1.1 or CL1.2: /// every address space is a superset of itself. /// CL2.0 adds: /// __generic is a superset of any address space except for __constant. + static bool isAddressSpaceSupersetOf(LangAS A, LangAS B) { + // Address spaces must match exactly. + return A == B || + // Otherwise in OpenCLC v2.0 s6.5.5: every address space except + // for __constant can be used as __generic. + (A == LangAS::opencl_generic && B != LangAS::opencl_constant); + } + + /// Returns true if the address space in these qualifiers is equal to or + /// a superset of the address space in the argument qualifiers. bool isAddressSpaceSupersetOf(Qualifiers other) const { - return - // Address spaces must match exactly. - getAddressSpace() == other.getAddressSpace() || - // Otherwise in OpenCLC v2.0 s6.5.5: every address space except - // for __constant can be used as __generic. - (getAddressSpace() == LangAS::opencl_generic && - other.getAddressSpace() != LangAS::opencl_constant); + return isAddressSpaceSupersetOf(getAddressSpace(), other.getAddressSpace()); } /// Determines if these qualifiers compatibly include another set. Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -1857,6 +1857,9 @@ "reference %diff{to %select{type|incomplete type}1 $ could not bind to an " "%select{rvalue|lvalue}2 of type $|could not bind to %select{rvalue|lvalue}2 of " "incompatible type}0,3">; +def err_reference_bind_temporary_addrspace : Error< + "reference of type %0 cannot bind to a temporary object because of " + "address space mismatch">; def err_reference_bind_init_list : Error< "reference to type %0 cannot bind to an initializer list">; def err_init_list_bad_dest_type : Error< Index: cfe/trunk/include/clang/Sema/Initialization.h =================================================================== --- cfe/trunk/include/clang/Sema/Initialization.h +++ cfe/trunk/include/clang/Sema/Initialization.h @@ -1012,6 +1012,9 @@ /// Reference binding drops qualifiers. FK_ReferenceInitDropsQualifiers, + /// Reference with mismatching address space binding to temporary. + FK_ReferenceAddrspaceMismatchTemporary, + /// Reference binding failed. FK_ReferenceInitFailed, Index: cfe/trunk/lib/Sema/SemaInit.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp +++ cfe/trunk/lib/Sema/SemaInit.cpp @@ -3344,6 +3344,7 @@ case FK_NonConstLValueReferenceBindingToVectorElement: case FK_NonConstLValueReferenceBindingToUnrelated: case FK_RValueReferenceBindingToLValue: + case FK_ReferenceAddrspaceMismatchTemporary: case FK_ReferenceInitDropsQualifiers: case FK_ReferenceInitFailed: case FK_ConversionFailed: @@ -4837,9 +4838,16 @@ Sequence.AddReferenceBindingStep(cv1T1IgnoreAS, /*bindingTemporary=*/true); - if (T1Quals.hasAddressSpace()) + if (T1Quals.hasAddressSpace()) { + if (!Qualifiers::isAddressSpaceSupersetOf(T1Quals.getAddressSpace(), + LangAS::Default)) { + Sequence.SetFailed( + InitializationSequence::FK_ReferenceAddrspaceMismatchTemporary); + return; + } Sequence.AddQualificationConversionStep(cv1T1, isLValueRef ? VK_LValue : VK_XValue); + } } /// Attempt character array initialization from a string literal @@ -8516,6 +8524,11 @@ << Args[0]->getSourceRange(); break; + case FK_ReferenceAddrspaceMismatchTemporary: + S.Diag(Kind.getLocation(), diag::err_reference_bind_temporary_addrspace) + << DestType << Args[0]->getSourceRange(); + break; + case FK_ReferenceInitDropsQualifiers: { QualType SourceType = OnlyArg->getType(); QualType NonRefType = DestType.getNonReferenceType(); @@ -8851,6 +8864,10 @@ OS << "reference initialization drops qualifiers"; break; + case FK_ReferenceAddrspaceMismatchTemporary: + OS << "reference with mismatching address space bound to temporary"; + break; + case FK_ReferenceInitFailed: OS << "reference initialization failed"; break; Index: cfe/trunk/test/SemaOpenCLCXX/address-space-references.cl =================================================================== --- cfe/trunk/test/SemaOpenCLCXX/address-space-references.cl +++ cfe/trunk/test/SemaOpenCLCXX/address-space-references.cl @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only + +__global const int& f(__global float &ref) { + return ref; // expected-error{{reference of type 'const __global int &' cannot bind to a temporary object because of address space mismatch}} +}