Partially address review comments. Remove Sema member, rename argument to
parameter, combine parameter check function, and use
diag::note_member_declared_here on structs with invalid types in them. Does not
yet show the chain of fields that are problematic, just the lowest one. Also
update event_t test for changed warning.
Hi rsmith,
http://llvm-reviews.chandlerc.com/D1052
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D1052?vs=2588&id=2727#toc
Files:
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
test/SemaOpenCL/event_t.cl
test/SemaOpenCL/invalid-kernel-parameters.cl
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -6423,16 +6423,18 @@
"invalid reinterpretation: sizes of %0 and %1 must match">;
def err_static_kernel : Error<
"kernel functions cannot be declared static">;
-def err_opencl_ptrptr_kernel_arg : Error<
- "kernel argument cannot be declared as a pointer to a pointer">;
+def err_opencl_ptrptr_kernel_param : Error<
+ "kernel parameter cannot be declared as a pointer to a pointer">;
def err_static_function_scope : Error<
"variables in function scope cannot be declared static">;
def err_opencl_bitfields : Error<
"bitfields are not supported in OpenCL">;
def err_opencl_vla : Error<
"variable length arrays are not supported in OpenCL">;
-def err_event_t_kernel_arg : Error<
- "the event_t type cannot be used to declare a kernel function argument">;
+def err_bad_kernel_param_type : Error<
+ "%0 cannot be used to declare a kernel function parameter">;
+def err_struct_with_pointers_kernel_param : Error<
+ "struct or union kernel parameters may not contain OpenCL objects">;
def err_event_t_global_var : Error<
"the event_t type cannot be used to declare a program scope variable">;
def err_event_t_struct_field : Error<
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -1446,6 +1446,8 @@
void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
void ActOnStartFunctionDeclarator();
void ActOnEndFunctionDeclarator();
+
+ void checkIsValidOpenCLKernelArgument(Declarator &D, ParmVarDecl *P);
NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TypeSourceInfo *TInfo,
LookupResult &Previous,
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -6042,6 +6042,143 @@
}
}
+enum OpenCLParamType {
+ ValidKernelParam,
+ PtrPtrKernelParam,
+ BoolKernelParam,
+ IntTypeKernelParam,
+ EventKernelParam,
+ HalfKernelParam,
+ PtrKernelParam,
+ RecordKernelParam
+};
+
+static OpenCLParamType getOpenCLKernelParameterType(QualType PT) {
+ if (PT->isPointerType()) {
+ QualType PointeeType = PT->getPointeeType();
+ return PointeeType->isPointerType() ? PtrPtrKernelParam : PtrKernelParam;
+ }
+
+ if (PT->isImageType())
+ return PtrKernelParam;
+
+ if (PT->isIntegerType()) {
+ if (PT->isBooleanType())
+ return BoolKernelParam;
+
+ if (const TypedefType *Typedef = dyn_cast<TypedefType>(PT)) {
+ const IdentifierInfo *Identifier = Typedef->getDecl()->getIdentifier();
+ StringRef Name = Identifier->getName();
+
+ if (Name == "size_t" ||
+ Name == "ptrdiff_t" ||
+ Name == "intptr_t" ||
+ Name == "uintptr_t") {
+ return IntTypeKernelParam;
+ }
+ }
+ }
+
+ if (PT->isEventT())
+ return EventKernelParam;
+
+ if (PT->isHalfType())
+ return HalfKernelParam;
+
+ if (PT->isRecordType())
+ return RecordKernelParam;
+
+ return ValidKernelParam;
+}
+
+static void checkIsValidOpenCLKernelParameter(Sema &S,
+ Declarator &D,
+ ParmVarDecl *Param) {
+ QualType PT = Param->getType();
+
+ switch (getOpenCLKernelParameterType(PT)) {
+ case PtrPtrKernelParam:
+ // OpenCL v1.2 s6.9.a:
+ // A kernel function argument cannot be declared as a
+ // pointer to a pointer type.
+ S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
+ D.setInvalidType();
+ return;
+
+ case BoolKernelParam:
+ case HalfKernelParam:
+ case IntTypeKernelParam:
+ // OpenCL v1.2 s6.9.k:
+ // Arguments to kernel functions in a program cannot be declared with the
+ // built-in scalar types bool, half, size_t, ptrdiff_t, intptr_t, and
+ // uintptr_t or a struct and/or union that contain fields declared to be
+ // one of these built-in scalar types.
+
+ case EventKernelParam:
+ // OpenCL v1.2 s6.8 n:
+ // A kernel function argument cannot be declared
+ // of event_t type.
+ S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
+ D.setInvalidType();
+ return;
+
+ case PtrKernelParam:
+ case ValidKernelParam:
+ return;
+
+ case RecordKernelParam:
+ break;
+ }
+
+ const RecordType *RT = PT->getAs<RecordType>();
+ assert(RT && "Should only have RecordType arguments at this point");
+
+ SmallVector<const RecordType *, 4> NestedStructQueue;
+ NestedStructQueue.push_back(RT);
+
+ while (!NestedStructQueue.empty()) {
+ const RecordType *RT = NestedStructQueue.pop_back_val();
+
+ const RecordDecl *RD = RT->getDecl();
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end(); I != E; ++I) {
+ const FieldDecl *FD = *I;
+
+ QualType QT = FD->getType();
+ switch (getOpenCLKernelParameterType(QT)) {
+ case ValidKernelParam:
+ break;
+
+ case PtrKernelParam:
+ case PtrPtrKernelParam:
+ // OpenCL v1.2 s6.9.p:
+ // Arguments to kernel functions that are declared to be a struct or union
+ // do not allow OpenCL objects to be passed as elements of the struct or
+ // union.
+ S.Diag(Param->getLocation(),
+ diag::err_struct_with_pointers_kernel_param);
+ S.Diag(FD->getLocation(), diag::note_member_declared_here)
+ << FD->getDeclName();
+ D.setInvalidType();
+ break;
+
+ case BoolKernelParam:
+ case HalfKernelParam:
+ case IntTypeKernelParam:
+ case EventKernelParam:
+ S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
+ S.Diag(FD->getLocation(), diag::note_member_declared_here)
+ << FD->getDeclName();
+ D.setInvalidType();
+ break;
+
+ case RecordKernelParam:
+ NestedStructQueue.push_back(QT->getAs<RecordType>());
+ }
+ }
+ }
+}
+
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
@@ -6777,34 +6914,18 @@
Diag(D.getIdentifierLoc(), diag::err_static_kernel);
D.setInvalidType();
}
-
+
// OpenCL v1.2, s6.9 -- Kernels can only have return type void.
if (!NewFD->getResultType()->isVoidType()) {
Diag(D.getIdentifierLoc(),
diag::err_expected_kernel_void_return_type);
D.setInvalidType();
}
-
+
for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
PE = NewFD->param_end(); PI != PE; ++PI) {
ParmVarDecl *Param = *PI;
- QualType PT = Param->getType();
-
- // OpenCL v1.2 s6.9.a:
- // A kernel function argument cannot be declared as a
- // pointer to a pointer type.
- if (PT->isPointerType() && PT->getPointeeType()->isPointerType()) {
- Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_arg);
- D.setInvalidType();
- }
-
- // OpenCL v1.2 s6.8 n:
- // A kernel function argument cannot be declared
- // of event_t type.
- if (PT->isEventT()) {
- Diag(Param->getLocation(), diag::err_event_t_kernel_arg);
- D.setInvalidType();
- }
+ checkIsValidOpenCLKernelParameter(*this, D, Param);
}
}
Index: test/SemaOpenCL/event_t.cl
===================================================================
--- test/SemaOpenCL/event_t.cl
+++ test/SemaOpenCL/event_t.cl
@@ -8,7 +8,7 @@
void foo(event_t evt); // expected-note {{passing argument to parameter 'evt' here}}
-void kernel ker(event_t argevt) { // expected-error {{the event_t type cannot be used to declare a kernel function argument}}
+void kernel ker(event_t argevt) { // expected-error {{'event_t' cannot be used to declare a kernel function parameter}}
event_t e;
constant event_t const_evt; // expected-error {{the event_t type can only be used with __private address space qualifier}}
foo(e);
Index: test/SemaOpenCL/invalid-kernel-parameters.cl
===================================================================
--- /dev/null
+++ test/SemaOpenCL/invalid-kernel-parameters.cl
@@ -0,0 +1,96 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+
+// Disallowed: parameters with type
+// bool, half, size_t, ptrdiff_t, intptr_t, and uintptr_t
+// or a struct / union with any of these types in them
+
+
+// These would normally come from a header with the OpenCL builtins
+typedef unsigned int size_t;
+typedef size_t ptrdiff_t;
+typedef size_t intptr_t;
+typedef size_t uintptr_t;
+
+
+kernel void bool_arg(bool x) { } // expected-error{{'bool' cannot be used to declare a kernel function parameter}}
+
+kernel void half_arg(half x) { } // expected-error{{'half' cannot be used to declare a kernel function parameter}}
+
+kernel void size_t_arg(size_t x) { } // expected-error{{'size_t' (aka 'unsigned int') cannot be used to declare a kernel function parameter}}
+
+kernel void ptrdiff_t_arg(ptrdiff_t x) { } // expected-error{{ptrdiff_t' (aka 'unsigned int') cannot be used to declare a kernel function parameter}}
+
+kernel void intptr_t_arg(intptr_t x) { } // expected-error{{'intptr_t' (aka 'unsigned int') cannot be used to declare a kernel function parameter}}
+
+kernel void uintptr_t_arg(uintptr_t x) { } // expected-error{{uintptr_t' (aka 'unsigned int') cannot be used to declare a kernel function parameter}}
+
+typedef struct ContainsBool
+{
+ bool x; // expected-note{{member 'x' declared here}}
+} ContainsBool;
+
+kernel void bool_in_struct_arg(ContainsBool x) { } // expected-error{{'ContainsBool' (aka 'struct ContainsBool') cannot be used to declare a kernel function parameter}}
+
+
+
+typedef struct FooImage2D
+{
+ image2d_t imageField; // expected-note{{member 'imageField' declared here}}
+} FooImage2D;
+
+kernel void image_in_struct_arg(FooImage2D arg) { } // expected-error{{struct or union kernel parameters may not contain OpenCL object}}
+
+typedef struct Foo
+{
+ int* ptrField; // expected-note{{member 'ptrField' declared here}}
+} Foo;
+
+kernel void pointer_in_struct_arg(Foo arg) { } // expected-error{{struct or union kernel parameters may not contain OpenCL object}}
+
+typedef union FooUnion
+{
+ int* ptrField; // expected-note{{member 'ptrField' declared here}}
+} FooUnion;
+
+kernel void pointer_in_union_arg(FooUnion arg) { }// expected-error{{struct or union kernel parameters may not contain OpenCL object}}
+
+typedef struct NestedPointer
+{
+ int x;
+ struct InnerNestedPointer
+ {
+ int* ptrField; // expected-note{{member 'ptrField' declared here}}
+ } inner;
+} NestedPointer;
+
+kernel void pointer_in_nested_struct_arg(NestedPointer arg) { }// expected-error{{struct or union kernel parameters may not contain OpenCL objects}}
+
+typedef struct NestedBool
+{
+ int x;
+ struct InnerNestedBool
+ {
+ bool boolField; // expected-note{{member 'boolField' declared here}}
+ } inner;
+} NestedBool;
+
+kernel void bool_in_nested_struct_arg(NestedBool arg) { } // expected-error{{'NestedBool' (aka 'struct NestedBool') cannot be used to declare a kernel function parameter}}
+
+
+// Check for note with a struct not defined inside the struct
+typedef struct NestedBool2Inner
+{
+ bool boolField; // expected-note{{member 'boolField' declared here}}
+} NestedBool2Inner;
+
+typedef struct NestedBool2
+{
+ int x;
+ NestedBool2Inner inner;
+} NestedBool2;
+
+kernel void bool_in_nested_struct_2_arg(NestedBool2 arg) { } // expected-error{{'NestedBool2' (aka 'struct NestedBool2') cannot be used to declare a kernel function parameter}}
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits