]> granicus.if.org Git - clang/commitdiff
[OpenCL] Disallow negative attribute arguments
authorAndrew Savonichev <andrew.savonichev@intel.com>
Thu, 6 Sep 2018 11:54:09 +0000 (11:54 +0000)
committerAndrew Savonichev <andrew.savonichev@intel.com>
Thu, 6 Sep 2018 11:54:09 +0000 (11:54 +0000)
Summary:
Negative arguments in kernel attributes are silently bitcast'ed to
unsigned, for example:

    __attribute__((reqd_work_group_size(1, -1, 1)))
    __kernel void k() {}

is a complete equivalent of:

    __attribute__((reqd_work_group_size(1, 4294967294, 1)))
    __kernel void k() {}

This is likely an error, so the patch forbids negative arguments in
several OpenCL attributes. Users who really want 4294967294 can still
use it as an unsigned representation.

Reviewers: Anastasia, yaxunl, bader

Reviewed By: Anastasia, yaxunl, bader

Subscribers: bader, cfe-commits

Differential Revision: https://reviews.llvm.org/D50259

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341539 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclAttr.cpp
test/SemaOpenCL/invalid-kernel-attrs.cl

index c1f0774d63acacdb43a5534cd8904f11b43c0cd7..03d8f7076ce2266b7fb80d972d21f93bda5a2dcc 100644 (file)
@@ -2529,6 +2529,8 @@ def err_attribute_argument_type : Error<
   "constant|a string|an identifier}1">;
 def err_attribute_argument_outof_range : Error<
   "%0 attribute requires integer constant between %1 and %2 inclusive">;
+def err_attribute_argument_negative : Error<
+  "negative argument is not allowed for %0 attribute">;
 def err_init_priority_object_attr : Error<
   "can only use 'init_priority' attribute on file-scope definitions "
   "of objects of class type">;
index d72b8fbb1aaca662f9d5f23b73b729f30a91995c..488299a970f1744ed18b7b277cfeeaa5760a6948 100644 (file)
@@ -227,9 +227,13 @@ static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); }
 
 /// If Expr is a valid integer constant, get the value of the integer
 /// expression and return success or failure. May output an error.
+///
+/// Negative argument is implicitly converted to unsigned, unless
+/// \p StrictlyUnsigned is true.
 template <typename AttrInfo>
 static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
-                                uint32_t &Val, unsigned Idx = UINT_MAX) {
+                                uint32_t &Val, unsigned Idx = UINT_MAX,
+                                bool StrictlyUnsigned = false) {
   llvm::APSInt I(32);
   if (Expr->isTypeDependent() || Expr->isValueDependent() ||
       !Expr->isIntegerConstantExpr(I, S.Context)) {
@@ -249,6 +253,11 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
     return false;
   }
 
+  if (StrictlyUnsigned && I.isSigned() && I.isNegative()) {
+    S.Diag(getAttrLoc(AI), diag::err_attribute_argument_negative) << AI;
+    return false;
+  }
+
   Val = (uint32_t)I.getZExtValue();
   return true;
 }
@@ -2766,7 +2775,8 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
   uint32_t WGSize[3];
   for (unsigned i = 0; i < 3; ++i) {
     const Expr *E = AL.getArgAsExpr(i);
-    if (!checkUInt32Argument(S, AL, E, WGSize[i], i))
+    if (!checkUInt32Argument(S, AL, E, WGSize[i], i,
+                             /*StrictlyUnsigned=*/true))
       return;
     if (WGSize[i] == 0) {
       S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
index a19a989f41bb85ef93392490332fc1f30f3a119e..9a0bcd83e9b7d4ef7efac8bf5bc27d2d895c9aa3 100644 (file)
@@ -37,3 +37,10 @@ kernel __attribute__((reqd_work_group_size(0,1,2))) void kernel13(){} // expecte
 __attribute__((intel_reqd_sub_group_size(8))) void kernel14(){} // expected-error {{attribute 'intel_reqd_sub_group_size' can only be applied to an OpenCL kernel}}
 kernel __attribute__((intel_reqd_sub_group_size(0))) void kernel15(){} // expected-error {{'intel_reqd_sub_group_size' attribute must be greater than 0}}
 kernel __attribute__((intel_reqd_sub_group_size(8))) __attribute__((intel_reqd_sub_group_size(16))) void kernel16() {}  //expected-warning{{attribute 'intel_reqd_sub_group_size' is already applied with different parameters}}
+
+__kernel __attribute__((work_group_size_hint(8,-16,32))) void neg1() {} //expected-error{{negative argument is not allowed for 'work_group_size_hint' attribute}}
+__kernel __attribute__((reqd_work_group_size(8,16,-32))) void neg2(){} // expected-error{{negative argument is not allowed for 'reqd_work_group_size' attribute}}
+
+// 4294967294 is a negative integer if treated as signed.
+// Should compile successfully, since we expect an unsigned.
+__kernel __attribute__((reqd_work_group_size(8,16,4294967294))) void ok1(){}