forked from OSchip/llvm-project
[SYCL] Prohibit arithmetic operations for incompatible pointers
Summary: This change enables OpenCL diagnostics for the pointers annotated with address space attribute SYCL mode. Move `isAddressSpaceOverlapping` method from PointerType to QualType. Reviewers: Anastasia, rjmccall Reviewed By: rjmccall Subscribers: rjmccall, jeroen.dobbelaere, Fznamznon, yaxunl, ebevhan, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D80317
This commit is contained in:
parent
872ee78f65
commit
e95ee300c0
|
@ -1064,6 +1064,21 @@ public:
|
|||
/// Return the address space of this type.
|
||||
inline LangAS getAddressSpace() const;
|
||||
|
||||
/// Returns true if address space qualifiers overlap with T address space
|
||||
/// qualifiers.
|
||||
/// OpenCL C defines conversion rules for pointers to different address spaces
|
||||
/// and notion of overlapping address spaces.
|
||||
/// CL1.1 or CL1.2:
|
||||
/// address spaces overlap iff they are they same.
|
||||
/// OpenCL C v2.0 s6.5.5 adds:
|
||||
/// __generic overlaps with any address space except for __constant.
|
||||
bool isAddressSpaceOverlapping(QualType T) const {
|
||||
Qualifiers Q = getQualifiers();
|
||||
Qualifiers TQ = T.getQualifiers();
|
||||
// Address spaces overlap if at least one of them is a superset of another
|
||||
return Q.isAddressSpaceSupersetOf(TQ) || TQ.isAddressSpaceSupersetOf(Q);
|
||||
}
|
||||
|
||||
/// Returns gc attribute of this type.
|
||||
inline Qualifiers::GC getObjCGCAttr() const;
|
||||
|
||||
|
@ -2631,22 +2646,6 @@ class PointerType : public Type, public llvm::FoldingSetNode {
|
|||
public:
|
||||
QualType getPointeeType() const { return PointeeType; }
|
||||
|
||||
/// Returns true if address spaces of pointers overlap.
|
||||
/// OpenCL v2.0 defines conversion rules for pointers to different
|
||||
/// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping
|
||||
/// address spaces.
|
||||
/// CL1.1 or CL1.2:
|
||||
/// address spaces overlap iff they are they same.
|
||||
/// CL2.0 adds:
|
||||
/// __generic overlaps with any address space except for __constant.
|
||||
bool isAddressSpaceOverlapping(const PointerType &other) const {
|
||||
Qualifiers thisQuals = PointeeType.getQualifiers();
|
||||
Qualifiers otherQuals = other.getPointeeType().getQualifiers();
|
||||
// Address spaces overlap if at least one of them is a superset of another
|
||||
return thisQuals.isAddressSpaceSupersetOf(otherQuals) ||
|
||||
otherQuals.isAddressSpaceSupersetOf(thisQuals);
|
||||
}
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
|
|
|
@ -2391,7 +2391,7 @@ static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
|
|||
return TC_NotApplicable;
|
||||
auto SrcPointeeType = SrcPtrType->getPointeeType();
|
||||
auto DestPointeeType = DestPtrType->getPointeeType();
|
||||
if (!DestPtrType->isAddressSpaceOverlapping(*SrcPtrType)) {
|
||||
if (!DestPointeeType.isAddressSpaceOverlapping(SrcPointeeType)) {
|
||||
msg = diag::err_bad_cxx_cast_addr_space_mismatch;
|
||||
return TC_Failed;
|
||||
}
|
||||
|
@ -2434,9 +2434,9 @@ void CastOperation::checkAddressSpaceCast(QualType SrcType, QualType DestType) {
|
|||
const PointerType *SrcPPtr = cast<PointerType>(SrcPtr);
|
||||
QualType DestPPointee = DestPPtr->getPointeeType();
|
||||
QualType SrcPPointee = SrcPPtr->getPointeeType();
|
||||
if (Nested ? DestPPointee.getAddressSpace() !=
|
||||
SrcPPointee.getAddressSpace()
|
||||
: !DestPPtr->isAddressSpaceOverlapping(*SrcPPtr)) {
|
||||
if (Nested
|
||||
? DestPPointee.getAddressSpace() != SrcPPointee.getAddressSpace()
|
||||
: !DestPPointee.isAddressSpaceOverlapping(SrcPPointee)) {
|
||||
Self.Diag(OpRange.getBegin(), DiagID)
|
||||
<< SrcType << DestType << Sema::AA_Casting
|
||||
<< SrcExpr.get()->getSourceRange();
|
||||
|
|
|
@ -10087,10 +10087,8 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
|
|||
if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType();
|
||||
|
||||
// if both are pointers check if operation is valid wrt address spaces
|
||||
if (S.getLangOpts().OpenCL && isLHSPointer && isRHSPointer) {
|
||||
const PointerType *lhsPtr = LHSExpr->getType()->castAs<PointerType>();
|
||||
const PointerType *rhsPtr = RHSExpr->getType()->castAs<PointerType>();
|
||||
if (!lhsPtr->isAddressSpaceOverlapping(*rhsPtr)) {
|
||||
if (isLHSPointer && isRHSPointer) {
|
||||
if (!LHSPointeeTy.isAddressSpaceOverlapping(RHSPointeeTy)) {
|
||||
S.Diag(Loc,
|
||||
diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
|
||||
<< LHSExpr->getType() << RHSExpr->getType() << 1 /*arithmetic op*/
|
||||
|
@ -11444,8 +11442,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
|
|||
if (LCanPointeeTy != RCanPointeeTy) {
|
||||
// Treat NULL constant as a special case in OpenCL.
|
||||
if (getLangOpts().OpenCL && !LHSIsNull && !RHSIsNull) {
|
||||
const PointerType *LHSPtr = LHSType->castAs<PointerType>();
|
||||
if (!LHSPtr->isAddressSpaceOverlapping(*RHSType->castAs<PointerType>())) {
|
||||
if (!LCanPointeeTy.isAddressSpaceOverlapping(RCanPointeeTy)) {
|
||||
Diag(Loc,
|
||||
diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
|
||||
<< LHSType << RHSType << 0 /* comparison */
|
||||
|
|
|
@ -74,6 +74,10 @@ char* cmp(_AS1 char *x, _AS2 char *y) {
|
|||
return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type ('_AS1 char *' and '_AS2 char *') which are pointers to non-overlapping address spaces}}
|
||||
}
|
||||
|
||||
char *sub(_AS1 char *x, _AS2 char *y) {
|
||||
return x - y; // expected-error {{arithmetic operation with operands of type ('_AS1 char *' and '_AS2 char *') which are pointers to non-overlapping address spaces}}
|
||||
}
|
||||
|
||||
struct SomeStruct {
|
||||
int a;
|
||||
long b;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
int *foo(__attribute__((opencl_private)) int *p,
|
||||
__attribute__((opencl_local)) int *l) {
|
||||
return p - l; // expected-error {{arithmetic operation with operands of type ('__private int *' and '__local int *') which are pointers to non-overlapping address spaces}}
|
||||
}
|
Loading…
Reference in New Issue