Skip to content

Commit 3b238ed

Browse files
committed
[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 llvm-svn: 338427
1 parent e1f3062 commit 3b238ed

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8079,6 +8079,15 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
80798079
if (PT->isRecordType())
80808080
return RecordKernelParam;
80818081

8082+
// Look into an array argument to check if it has a forbidden type.
8083+
if (PT->isArrayType()) {
8084+
const Type *UnderlyingTy = PT->getPointeeOrArrayElementType();
8085+
// Call ourself to check an underlying type of an array. Since the
8086+
// getPointeeOrArrayElementType returns an innermost type which is not an
8087+
// array, this recusive call only happens once.
8088+
return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0));
8089+
}
8090+
80828091
return ValidKernelParam;
80838092
}
80848093

@@ -8146,9 +8155,14 @@ static void checkIsValidOpenCLKernelParameter(
81468155
SmallVector<const FieldDecl *, 4> HistoryStack;
81478156
HistoryStack.push_back(nullptr);
81488157

8149-
const RecordDecl *PD = PT->castAs<RecordType>()->getDecl();
8150-
VisitStack.push_back(PD);
8158+
// At this point we already handled everything except of a RecordType or
8159+
// an ArrayType of a RecordType.
8160+
assert((PT->isArrayType() || PT->isRecordType()) && "Unexpected type.");
8161+
const RecordType *RecTy =
8162+
PT->getPointeeOrArrayElementType()->getAs<RecordType>();
8163+
const RecordDecl *OrigRecDecl = RecTy->getDecl();
81518164

8165+
VisitStack.push_back(RecTy->getDecl());
81528166
assert(VisitStack.back() && "First decl null?");
81538167

81548168
do {
@@ -8167,7 +8181,15 @@ static void checkIsValidOpenCLKernelParameter(
81678181
const RecordDecl *RD;
81688182
if (const FieldDecl *Field = dyn_cast<FieldDecl>(Next)) {
81698183
HistoryStack.push_back(Field);
8170-
RD = Field->getType()->castAs<RecordType>()->getDecl();
8184+
8185+
QualType FieldTy = Field->getType();
8186+
// Other field types (known to be valid or invalid) are handled while we
8187+
// walk around RecordDecl::fields().
8188+
assert((FieldTy->isArrayType() || FieldTy->isRecordType()) &&
8189+
"Unexpected type.");
8190+
const Type *FieldRecTy = FieldTy->getPointeeOrArrayElementType();
8191+
8192+
RD = FieldRecTy->castAs<RecordType>()->getDecl();
81718193
} else {
81728194
RD = cast<RecordDecl>(Next);
81738195
}
@@ -8204,8 +8226,8 @@ static void checkIsValidOpenCLKernelParameter(
82048226
S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
82058227
}
82068228

8207-
S.Diag(PD->getLocation(), diag::note_within_field_of_type)
8208-
<< PD->getDeclName();
8229+
S.Diag(OrigRecDecl->getLocation(), diag::note_within_field_of_type)
8230+
<< OrigRecDecl->getDeclName();
82098231

82108232
// We have an error, now let's go back up through history and show where
82118233
// the offending field came from

clang/test/SemaOpenCL/invalid-kernel-parameters.cl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,16 @@ struct AlsoUser // expected-note{{within field of type 'AlsoUser' declared here}
136136
};
137137

138138
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}}
139+
140+
struct ArrayOfPtr // expected-note{{within field of type 'ArrayOfPtr' declared here}}
141+
{
142+
float *arr[3]; // expected-note{{field of illegal type 'float *[3]' declared here}}
143+
// expected-note@-1{{field of illegal type 'float *[3]' declared here}}
144+
};
145+
kernel void array_of_ptr(struct ArrayOfPtr arr) {} // expected-error{{struct kernel parameters may not contain pointers}}
146+
147+
struct ArrayOfStruct // expected-note{{within field of type 'ArrayOfStruct' declared here}}
148+
{
149+
struct ArrayOfPtr arr[3]; // expected-note{{within field of type 'struct ArrayOfPtr [3]' declared here}}
150+
};
151+
kernel void array_of_struct(struct ArrayOfStruct arr) {} // expected-error{{struct kernel parameters may not contain pointers}}

0 commit comments

Comments
 (0)