Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -1825,10 +1825,8 @@ "%diff{to type $ cannot bind to a value of unrelated type $|" "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">; + "binding reference %diff{of type $ to value of type $|to value}0,1 " + "%select{drops %3 qualifier%plural{1:|2:|4:|:s}4|changes address space}2">; def err_reference_bind_failed : Error< "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 " Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -4623,7 +4623,10 @@ // - 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())) { + // For address spaces, we interpret this to mean that an addr space + // of a reference "cv1 T1" is a superset of addr space of "cv2 T2". + if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile() && + T1Quals.isAddressSpaceSupersetOf(T2Quals))) { if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) @@ -4632,7 +4635,10 @@ ConvOvlResult); else if (!InitCategory.isLValue()) Sequence.SetFailed( - InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); + T1Quals.isAddressSpaceSupersetOf(T2Quals) + ? InitializationSequence:: + FK_NonConstLValueReferenceBindingToTemporary + : InitializationSequence::FK_ReferenceInitDropsQualifiers); else { InitializationSequence::FailureKind FK; switch (RefRelationship) { @@ -8470,11 +8476,16 @@ Qualifiers DroppedQualifiers = SourceType.getQualifiers() - NonRefType.getQualifiers(); - S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) - << SourceType - << NonRefType - << DroppedQualifiers.getCVRQualifiers() - << Args[0]->getSourceRange(); + if (!NonRefType.getQualifiers().isAddressSpaceSupersetOf( + SourceType.getQualifiers())) + S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) + << NonRefType << SourceType << 1 /*addr space*/ + << Args[0]->getSourceRange(); + else + S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) + << NonRefType << SourceType << 0 /*cv quals*/ + << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers()) + << DroppedQualifiers.getCVRQualifiers() << Args[0]->getSourceRange(); break; } Index: test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp =================================================================== --- test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp +++ test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp @@ -122,8 +122,8 @@ const double& rcd2 = 2; double&& rrd = 2; - const volatile int cvi = 1; - const int& r2 = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}} + const volatile int cvi = 1; + const int& r2 = cvi; // expected-error{{binding reference of type 'const int' to value of type 'const volatile int' drops 'volatile' qualifier}} double d; double&& rrd2 = d; // expected-error{{rvalue reference to type 'double' cannot bind to lvalue of type 'double'}} Index: test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp =================================================================== --- test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp +++ test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp @@ -69,10 +69,10 @@ volatile const int ivc) { volatile Base &bvr1 = b; volatile Base &bvr2 = d; - volatile Base &bvr3 = bvc; // expected-error{{binding value of type 'const volatile Base' to reference to type 'volatile Base' drops 'const' qualifier}} - volatile Base &bvr4 = dvc; // expected-error{{binding value of type 'const volatile Derived' to reference to type 'volatile Base' drops 'const' qualifier}} - - volatile int &ir = ivc; // expected-error{{binding value of type 'const volatile int' to reference to type 'volatile int' drops 'const' qualifier}} + volatile Base &bvr3 = bvc; // expected-error{{binding reference of type 'volatile Base' to value of type 'const volatile Base' drops 'const' qualifier}} + volatile Base &bvr4 = dvc; // expected-error{{binding reference of type 'volatile Base' to value of type 'const volatile Derived' drops 'const' qualifier}} + + volatile int &ir = ivc; // expected-error{{binding reference of type 'volatile int' to value of type 'const volatile int' drops 'const' qualifier}} const volatile Base &bcvr1 = b; const volatile Base &bcvr2 = d; @@ -123,8 +123,8 @@ const Base &br3 = create(); const Base &br4 = create(); - const Base &br5 = create(); // expected-error{{binding value of type 'const volatile Base' to reference to type 'const Base' drops 'volatile' qualifier}} - const Base &br6 = create(); // expected-error{{binding value of type 'const volatile Derived' to reference to type 'const Base' drops 'volatile' qualifier}} + const Base &br5 = create(); // expected-error{{binding reference of type 'const Base' to value of type 'const volatile Base' drops 'volatile' qualifier}} + const Base &br6 = create(); // expected-error{{binding reference of type 'const Base' to value of type 'const volatile Derived' drops 'volatile' qualifier}} const int &ir = create(); } Index: test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp =================================================================== --- test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp +++ test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp @@ -28,8 +28,8 @@ A &&ar6 = static_cast(xvalue()); A &&ar7 = static_cast(prvalue()); - A &&ar8 = static_cast(prvalue()); // expected-error {{binding value of type 'const A' to reference to type 'A' drops 'const' qualifier}} - A &&ar9 = static_cast(lvalue()); // expected-error {{cannot cast from lvalue of type 'const A'}} + A &&ar8 = static_cast(prvalue()); // expected-error {{binding reference of type 'A' to value of type 'const A' drops 'const' qualifier}} + A &&ar9 = static_cast(lvalue()); // expected-error {{cannot cast from lvalue of type 'const A'}} A &&ar10 = static_cast(xvalue()); // expected-error {{cannot cast from rvalue of type 'const A'}} const A &&ar11 = static_cast(prvalue()); @@ -39,5 +39,5 @@ const A &&ar15 = static_cast(prvalue()); const A &&ar16 = static_cast(lvalue()); - const A &&ar17 = static_cast(prvalue()); // expected-error {{binding value of type 'const volatile A' to reference to type 'const A' drops 'volatile' qualifier}} + const A &&ar17 = static_cast(prvalue()); // expected-error {{binding reference of type 'const A' to value of type 'const volatile A' drops 'volatile' qualifier}} } Index: test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp =================================================================== --- test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp +++ test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp @@ -21,20 +21,20 @@ }(); }(); - int a; - [=]{ - [&] { - int &x = a; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const' qualifier}} - int &x2 = a; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const' qualifier}} - }(); - }(); + int a; + [=] { + [&] { + int &x = a; // expected-error{{binding reference of type 'int' to value of type 'const int' drops 'const' qualifier}} + int &x2 = a; // expected-error{{binding reference of type 'int' to value of type 'const int' drops 'const' qualifier}} + }(); + }(); - [=]{ - [&a] { - [&] { - int &x = a; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const' qualifier}} - int &x2 = a; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const' qualifier}} + [=] { + [&a] { + [&] { + int &x = a; // expected-error{{binding reference of type 'int' to value of type 'const int' drops 'const' qualifier}} + int &x2 = a; // expected-error{{binding reference of type 'int' to value of type 'const int' drops 'const' qualifier}} }(); - }(); - }(); + }(); + }(); } Index: test/Misc/diag-template-diffing.cpp =================================================================== --- test/Misc/diag-template-diffing.cpp +++ test/Misc/diag-template-diffing.cpp @@ -1252,7 +1252,7 @@ void foo(const T &t) { T &t2 = t; } -// CHECK-ELIDE-NOTREE: binding value of type 'const condition<...>' to reference to type 'condition<...>' drops 'const' qualifier +// CHECK-ELIDE-NOTREE: binding reference of type 'condition<...>' to value of type 'const condition<...>' drops 'const' qualifier } namespace BoolArgumentBitExtended { Index: test/SemaCXX/builtins-arm.cpp =================================================================== --- test/SemaCXX/builtins-arm.cpp +++ test/SemaCXX/builtins-arm.cpp @@ -2,5 +2,5 @@ // va_list on ARM AAPCS is struct { void* __ap }. int test1(const __builtin_va_list &ap) { - return __builtin_va_arg(ap, int); // expected-error {{binding value of type 'const __builtin_va_list' to reference to type '__builtin_va_list' drops 'const' qualifier}} + return __builtin_va_arg(ap, int); // expected-error {{binding reference of type '__builtin_va_list' to value of type 'const __builtin_va_list' drops 'const' qualifier}} } 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 @@ -6,31 +6,31 @@ volatile ptr vp, const volatile ptr cvp, restrict volatile ptr rvp, 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& 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& p2 = cp; // expected-error {{drops 'const' qualifier}} + 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 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& 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& 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 '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/SemaCXX/references.cpp =================================================================== --- test/SemaCXX/references.cpp +++ test/SemaCXX/references.cpp @@ -55,13 +55,13 @@ void test5() { // const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0 const volatile int cvi = 1; - const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}} + const int& r = cvi; // expected-error{{binding reference of type 'const int' to value of type 'const volatile int' drops 'volatile' qualifier}} #if __cplusplus >= 201103L - const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}} + const int& r2{cvi}; // expected-error{{binding reference of type 'const int' to value of type 'const volatile int' drops 'volatile' qualifier}} const int a = 2; - int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}} + int& r3{a}; // expected-error{{binding reference of type 'int' to value of type 'const int' drops 'const' qualifier}} const int&& r4{a}; // expected-error{{rvalue reference to type 'const int' cannot bind to lvalue of type 'const int'}} 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 reference of type '__global int' to value of type '__generic int' changes address space}} + static_cast<__global const int &>(gen); //expected-error{{binding reference of type 'const __global int' to value of type '__generic int' changes address space}} + static_cast<__global int &>(glob); //expected-error{{binding reference of type '__global int' to value of type 'const __global int' drops 'const' qualifier}} + static_cast<__local int &>(glob); //expected-error{{binding reference of type '__local int' to value of type 'const __global 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}} +} Index: test/SemaOpenCLCXX/address-space-references.cl =================================================================== --- /dev/null +++ test/SemaOpenCLCXX/address-space-references.cl @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only + +int bar(const __global unsigned int &i); // expected-note{{passing argument to parameter 'i' here}} +//FIXME: With the overload below the call should be resolved +// successfully. However, current overload resolution logic +// can't detect this case and therefore fails. +int bar(const unsigned int &i); + +void foo() { + bar(1) // expected-error{{binding reference of type 'const __global unsigned int' to value of type 'int' changes address space}} +}