diff options
-rw-r--r-- | clang/include/clang/AST/Type.h | 20 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/include/clang/Sema/Initialization.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 19 | ||||
-rw-r--r-- | clang/test/SemaOpenCLCXX/address-space-references.cl | 5 |
5 files changed, 41 insertions, 9 deletions
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 3f71a7ec6ff..00a2b764337 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -460,21 +460,25 @@ public: 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. diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 761bd22819a..d34720c9faf 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1857,6 +1857,9 @@ 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 " "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< diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h index 14d8aa8dabf..1c522e49bc6 100644 --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/include/clang/Sema/Initialization.h @@ -1012,6 +1012,9 @@ public: /// Reference binding drops qualifiers. FK_ReferenceInitDropsQualifiers, + /// Reference with mismatching address space binding to temporary. + FK_ReferenceAddrspaceMismatchTemporary, + /// Reference binding failed. FK_ReferenceInitFailed, diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 45456aff364..25aff40f26f 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3344,6 +3344,7 @@ bool InitializationSequence::isAmbiguous() const { 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 @@ static void TryReferenceInitializationCore(Sema &S, 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 @@ bool InitializationSequence::Diagnose(Sema &S, << 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 @@ void InitializationSequence::dump(raw_ostream &OS) const { 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; diff --git a/clang/test/SemaOpenCLCXX/address-space-references.cl b/clang/test/SemaOpenCLCXX/address-space-references.cl new file mode 100644 index 00000000000..c359bbd713a --- /dev/null +++ b/clang/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}} +} |