asavonic updated this revision to Diff 157470. asavonic added a comment. Moved another chunk from https://reviews.llvm.org/D49725
Repository: rC Clang https://reviews.llvm.org/D49723 Files: lib/Sema/SemaDecl.cpp test/SemaOpenCL/invalid-kernel-parameters.cl Index: test/SemaOpenCL/invalid-kernel-parameters.cl =================================================================== --- test/SemaOpenCL/invalid-kernel-parameters.cl +++ test/SemaOpenCL/invalid-kernel-parameters.cl @@ -136,3 +136,16 @@ }; 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@-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}} Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -8079,6 +8079,15 @@ 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 @@ 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,13 @@ const RecordDecl *RD; if (const FieldDecl *Field = dyn_cast<FieldDecl>(Next)) { HistoryStack.push_back(Field); - RD = Field->getType()->castAs<RecordType>()->getDecl(); + + // Other field types (known to be valid or invalid) are handled while we + // walk around RecordDecl::fields(). + assert((PT->isArrayType() || PT->isRecordType()) && "Unexpected type."); + const Type *FieldRecTy = Field->getType()->getPointeeOrArrayElementType(); + + RD = FieldRecTy->castAs<RecordType>()->getDecl(); } else { RD = cast<RecordDecl>(Next); } @@ -8204,8 +8224,8 @@ 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
Index: test/SemaOpenCL/invalid-kernel-parameters.cl =================================================================== --- test/SemaOpenCL/invalid-kernel-parameters.cl +++ test/SemaOpenCL/invalid-kernel-parameters.cl @@ -136,3 +136,16 @@ }; 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@-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}} Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -8079,6 +8079,15 @@ 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 @@ 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,13 @@ const RecordDecl *RD; if (const FieldDecl *Field = dyn_cast<FieldDecl>(Next)) { HistoryStack.push_back(Field); - RD = Field->getType()->castAs<RecordType>()->getDecl(); + + // Other field types (known to be valid or invalid) are handled while we + // walk around RecordDecl::fields(). + assert((PT->isArrayType() || PT->isRecordType()) && "Unexpected type."); + const Type *FieldRecTy = Field->getType()->getPointeeOrArrayElementType(); + + RD = FieldRecTy->castAs<RecordType>()->getDecl(); } else { RD = cast<RecordDecl>(Next); } @@ -8204,8 +8224,8 @@ 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
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits