Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -1824,9 +1824,10 @@ "cannot bind to a value of unrelated type}1,2">; def err_reference_bind_drops_quals : Error< "binding value %diff{of type $ to reference to type $|to reference}0,1 " - "drops %select{<>|'const'|'restrict'|'const' and 'restrict'|" - "'volatile'|'const' and 'volatile'|'restrict' and 'volatile'|" - "'const', 'restrict', and 'volatile'}2 qualifier%plural{1:|2:|4:|:s}2">; + "drops %2 qualifier%plural{1:|2:|4:|:s}3">; +def err_reference_bind_changes_addr_space : Error< + "binding value %diff{of type $ to reference to type $|to reference}0,1 " + "changes address space">; def err_reference_bind_failed : Error< "reference %diff{to type $ could not bind to an %select{rvalue|lvalue}1 of " "type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">; Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -4596,7 +4596,9 @@ // - Otherwise, the reference shall be an lvalue reference to a // non-volatile const type (i.e., cv1 shall be const), or the reference // shall be an rvalue reference. - if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) { + if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile() && + // addr space must be a superset. + T1Quals.isAddressSpaceSupersetOf(T2Quals))) { if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) @@ -8439,11 +8441,18 @@ Qualifiers DroppedQualifiers = SourceType.getQualifiers() - NonRefType.getQualifiers(); - S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) - << SourceType - << NonRefType - << DroppedQualifiers.getCVRQualifiers() - << Args[0]->getSourceRange(); + if (DroppedQualifiers.hasAddressSpace()) + S.Diag(Kind.getLocation(), diag::err_reference_bind_changes_addr_space) + << SourceType + << NonRefType + << Args[0]->getSourceRange(); + else + S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) + << SourceType + << NonRefType + << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers()) + << DroppedQualifiers.getCVRQualifiers() + << Args[0]->getSourceRange(); break; } Index: test/SemaCXX/err_reference_bind_drops_quals.cpp =================================================================== --- test/SemaCXX/err_reference_bind_drops_quals.cpp +++ test/SemaCXX/err_reference_bind_drops_quals.cpp @@ -7,30 +7,30 @@ const restrict volatile ptr crvp) { ptr& p1 = p; ptr& p2 = cp; // expected-error {{drops 'const' qualifier}} - ptr& p3 = rp; // expected-error {{drops 'restrict' qualifier}} - ptr& p4 = crp; // expected-error {{drops 'const' and 'restrict' qualifiers}} + ptr& p3 = rp; // expected-error {{drops '__restrict' qualifier}} + ptr& p4 = crp; // expected-error {{drops 'const __restrict' qualifiers}} ptr& p5 = vp; // expected-error {{drops 'volatile' qualifier}} - ptr& p6 = cvp; // expected-error {{drops 'const' and 'volatile' qualifiers}} - ptr& p7 = rvp; // expected-error {{drops 'restrict' and 'volatile' qualifiers}} - ptr& p8 = crvp; // expected-error {{drops 'const', 'restrict', and 'volatile' qualifiers}} + ptr& p6 = cvp; // expected-error {{drops 'const volatile' qualifiers}} + ptr& p7 = rvp; // expected-error {{drops 'volatile __restrict' qualifiers}} + ptr& p8 = crvp; // expected-error {{drops 'const volatile __restrict' qualifiers}} const ptr& cp1 = p; const ptr& cp2 = cp; - const ptr& cp3 = rp; // expected-error {{drops 'restrict' qualifier}} - const ptr& cp4 = crp; // expected-error {{drops 'restrict' qualifier}} + const ptr& cp3 = rp; // expected-error {{drops '__restrict' qualifier}} + const ptr& cp4 = crp; // expected-error {{drops '__restrict' qualifier}} const ptr& cp5 = vp; // expected-error {{drops 'volatile' qualifier}} const ptr& cp6 = cvp; // expected-error {{drops 'volatile' qualifier}} - const ptr& cp7 = rvp; // expected-error {{drops 'restrict' and 'volatile' qualifiers}} - const ptr& cp8 = crvp; // expected-error {{drops 'restrict' and 'volatile' qualifiers}} + const ptr& cp7 = rvp; // expected-error {{drops 'volatile __restrict' qualifiers}} + const ptr& cp8 = crvp; // expected-error {{drops 'volatile __restrict' qualifiers}} const volatile ptr& cvp1 = p; const volatile ptr& cvp2 = cp; - const volatile ptr& cvp3 = rp; // expected-error {{drops 'restrict' qualifier}} - const volatile ptr& cvp4 = crp; // expected-error {{drops 'restrict' qualifier}} + const volatile ptr& cvp3 = rp; // expected-error {{drops '__restrict' qualifier}} + const volatile ptr& cvp4 = crp; // expected-error {{drops '__restrict' qualifier}} const volatile ptr& cvp5 = vp; const volatile ptr& cvp6 = cvp; - const volatile ptr& cvp7 = rvp; // expected-error {{drops 'restrict' qualifier}} - const volatile ptr& cvp8 = crvp; // expected-error {{drops 'restrict' qualifier}} + const volatile ptr& cvp7 = rvp; // expected-error {{drops '__restrict' qualifier}} + const volatile ptr& cvp8 = crvp; // expected-error {{drops '__restrict' qualifier}} const restrict volatile ptr& crvp1 = p; const restrict volatile ptr& crvp2 = cp; Index: test/SemaOpenCLCXX/address-space-castoperators.cpp =================================================================== --- /dev/null +++ test/SemaOpenCLCXX/address-space-castoperators.cpp @@ -0,0 +1,17 @@ +//RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify + +void test_ref(int &gen, __global const int& glob){ +static_cast<__global int&>(gen); // expected-error{{binding value of type '__generic int' to reference to type '__global int' changes address space}} +static_cast<__global const int&>(gen); //expected-error{{binding value of type '__generic int' to reference to type 'const __global int' changes address space}} +static_cast<__global int&>(glob); //expected-error{{binding value of type 'const __global int' to reference to type '__global int' drops 'const' qualifier}} +static_cast<__local int&>(glob); //expected-error{{binding value of type 'const __global int' to reference to type '__local int' changes address space}} +static_cast<__generic const int&>(glob); //expected-warning{{expression result unused}} +} + +void test_ptr(int *gen, __global const int* glob){ + static_cast<__global int*>(gen); // expected-error{{static_cast from '__generic int *' to '__global int *' is not allowed}} + static_cast<__global const int*>(gen); //expected-error{{static_cast from '__generic int *' to 'const __global int *' is not allowed}} + static_cast<__global int*>(glob); //expected-error{{static_cast from 'const __global int *' to '__global int *' is not allowed}} + static_cast<__local int*>(glob); //expected-error{{static_cast from 'const __global int *' to '__local int *' is not allowed}} + static_cast<__generic const int*>(glob); //expected-warning{{expression result unused}} +}