diff options
author | Alexey Sotkin <alexey.sotkin@intel.com> | 2018-07-31 19:47:19 +0000 |
---|---|---|
committer | Alexey Sotkin <alexey.sotkin@intel.com> | 2018-07-31 19:47:19 +0000 |
commit | e9901bde15692e135ee2b98005f5fb8cdc23fcd5 (patch) | |
tree | 31464a45dac318ebcacc3c2eed449bedf0164f03 /lib/Sema/SemaDecl.cpp | |
parent | 0065b256efa39476c9d32097b06c80a50356e27c (diff) | |
download | clang-e9901bde15692e135ee2b98005f5fb8cdc23fcd5.tar.gz |
[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
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338427 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2e871d6029..941ffefeed 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8079,6 +8079,15 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) { 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 checkIsValidOpenCLKernelParameter( 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 checkIsValidOpenCLKernelParameter( 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 checkIsValidOpenCLKernelParameter( 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 |