Author: Alexey Bader
Date: 2020-05-22T13:43:24+03:00
New Revision: e95ee300c0530158d86430fd82ffabd36262e862

URL: 
https://github.com/llvm/llvm-project/commit/e95ee300c0530158d86430fd82ffabd36262e862
DIFF: 
https://github.com/llvm/llvm-project/commit/e95ee300c0530158d86430fd82ffabd36262e862.diff

LOG: [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

Added: 
    clang/test/SemaCXX/address-space-arithmetic.cpp

Modified: 
    clang/include/clang/AST/Type.h
    clang/lib/Sema/SemaCast.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/test/Sema/address_spaces.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 21b14de997cb..ed31dea925f3 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1064,6 +1064,21 @@ class QualType {
   /// 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 
diff erent 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 
diff erent
-  /// 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); }
 

diff  --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index a4fe90f79eb9..fe4fcdd01301 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -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();

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 93e67ad2940c..261e69b44052 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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 */

diff  --git a/clang/test/Sema/address_spaces.c 
b/clang/test/Sema/address_spaces.c
index 5425ef75b64e..6eb93f1625c7 100644
--- a/clang/test/Sema/address_spaces.c
+++ b/clang/test/Sema/address_spaces.c
@@ -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;

diff  --git a/clang/test/SemaCXX/address-space-arithmetic.cpp 
b/clang/test/SemaCXX/address-space-arithmetic.cpp
new file mode 100644
index 000000000000..af72bc7624b3
--- /dev/null
+++ b/clang/test/SemaCXX/address-space-arithmetic.cpp
@@ -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}}
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to