r338427 - [OpenCL] Check for invalid kernel arguments in array types

via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 31 12:47:19 PDT 2018


Author: AlexeySotkin
Date: Tue Jul 31 12:47:19 2018
New Revision: 338427

URL: http://llvm.org/viewvc/llvm-project?rev=338427&view=rev
Log:
[OpenCL] Check for invalid kernel arguments in array types

Summary:
OpenCL specification forbids use of several types as kernel arguments.
This patch improves existing diagnostic to look through arrays.

Patch by: Andrew Savonichev

Reviewers: Anastasia, yaxunl

Subscribers: yaxunl, Anastasia, cfe-commits

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

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaOpenCL/invalid-kernel-parameters.cl

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=338427&r1=338426&r2=338427&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jul 31 12:47:19 2018
@@ -8079,6 +8079,15 @@ static OpenCLParamType getOpenCLKernelPa
   if (PT->isRecordType())
     return RecordKernelParam;
 
+  // Look into an array argument to check if it has a forbidden type.
+  if (PT->isArrayType()) {
+    const Type *UnderlyingTy = PT->getPointeeOrArrayElementType();
+    // Call ourself to check an underlying type of an array. Since the
+    // getPointeeOrArrayElementType returns an innermost type which is not an
+    // array, this recusive call only happens once.
+    return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0));
+  }
+
   return ValidKernelParam;
 }
 
@@ -8146,9 +8155,14 @@ static void checkIsValidOpenCLKernelPara
   SmallVector<const FieldDecl *, 4> HistoryStack;
   HistoryStack.push_back(nullptr);
 
-  const RecordDecl *PD = PT->castAs<RecordType>()->getDecl();
-  VisitStack.push_back(PD);
+  // At this point we already handled everything except of a RecordType or
+  // an ArrayType of a RecordType.
+  assert((PT->isArrayType() || PT->isRecordType()) && "Unexpected type.");
+  const RecordType *RecTy =
+      PT->getPointeeOrArrayElementType()->getAs<RecordType>();
+  const RecordDecl *OrigRecDecl = RecTy->getDecl();
 
+  VisitStack.push_back(RecTy->getDecl());
   assert(VisitStack.back() && "First decl null?");
 
   do {
@@ -8167,7 +8181,15 @@ static void checkIsValidOpenCLKernelPara
     const RecordDecl *RD;
     if (const FieldDecl *Field = dyn_cast<FieldDecl>(Next)) {
       HistoryStack.push_back(Field);
-      RD = Field->getType()->castAs<RecordType>()->getDecl();
+
+      QualType FieldTy = Field->getType();
+      // Other field types (known to be valid or invalid) are handled while we
+      // walk around RecordDecl::fields().
+      assert((FieldTy->isArrayType() || FieldTy->isRecordType()) &&
+             "Unexpected type.");
+      const Type *FieldRecTy = FieldTy->getPointeeOrArrayElementType();
+
+      RD = FieldRecTy->castAs<RecordType>()->getDecl();
     } else {
       RD = cast<RecordDecl>(Next);
     }
@@ -8204,8 +8226,8 @@ static void checkIsValidOpenCLKernelPara
         S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
       }
 
-      S.Diag(PD->getLocation(), diag::note_within_field_of_type)
-        << PD->getDeclName();
+      S.Diag(OrigRecDecl->getLocation(), diag::note_within_field_of_type)
+          << OrigRecDecl->getDeclName();
 
       // We have an error, now let's go back up through history and show where
       // the offending field came from

Modified: cfe/trunk/test/SemaOpenCL/invalid-kernel-parameters.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/invalid-kernel-parameters.cl?rev=338427&r1=338426&r2=338427&view=diff
==============================================================================
--- cfe/trunk/test/SemaOpenCL/invalid-kernel-parameters.cl (original)
+++ cfe/trunk/test/SemaOpenCL/invalid-kernel-parameters.cl Tue Jul 31 12:47:19 2018
@@ -136,3 +136,16 @@ struct AlsoUser // expected-note{{within
 };
 
 kernel void pointer_in_nested_struct_arg_2(struct Valid valid, struct NestedPointer arg, struct AlsoUser also) { } // expected-error 2 {{struct kernel parameters may not contain pointers}}
+
+struct ArrayOfPtr // expected-note{{within field of type 'ArrayOfPtr' declared here}}
+{
+  float *arr[3]; // expected-note{{field of illegal type 'float *[3]' declared here}}
+                 // expected-note at -1{{field of illegal type 'float *[3]' declared here}}
+};
+kernel void array_of_ptr(struct ArrayOfPtr arr) {} // expected-error{{struct kernel parameters may not contain pointers}}
+
+struct ArrayOfStruct // expected-note{{within field of type 'ArrayOfStruct' declared here}}
+{
+  struct ArrayOfPtr arr[3]; // expected-note{{within field of type 'struct ArrayOfPtr [3]' declared here}}
+};
+kernel void array_of_struct(struct ArrayOfStruct arr) {} // expected-error{{struct kernel parameters may not contain pointers}}




More information about the cfe-commits mailing list