diff options
author | Anastasia Stulova <anastasia.stulova@arm.com> | 2019-06-05 14:03:34 +0000 |
---|---|---|
committer | Anastasia Stulova <anastasia.stulova@arm.com> | 2019-06-05 14:03:34 +0000 |
commit | 5145b1e4421adb3ac7e558cb88c9a2100ccb2b44 (patch) | |
tree | 597b0c357a9ac773f09037432ebda68a17ea0a1b | |
parent | 22e99c434fb65ca8a9d5e3dbf5db5965681ce5c3 (diff) | |
download | bcm5719-llvm-5145b1e4421adb3ac7e558cb88c9a2100ccb2b44.tar.gz bcm5719-llvm-5145b1e4421adb3ac7e558cb88c9a2100ccb2b44.zip |
[Sema] Prevent binding incompatible addr space ref to temporaries
References to arbitrary address spaces can't always be bound to
temporaries. This change extends the reference binding logic to
check that the address space of a temporary can be implicitly
converted to the address space in a reference when temporary
materialization is performed.
Differential Revision: https://reviews.llvm.org/D61318
llvm-svn: 362604
-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}} +} |