[clang] [SYCL] Basic diagnostics for the sycl_kernel_entry_point attribute. (PR #120327)
Tom Honermann via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 8 10:27:57 PST 2025
================
@@ -206,3 +208,124 @@ void SemaSYCL::handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (SemaRef.Context)
SYCLKernelEntryPointAttr(SemaRef.Context, AL, TSI));
}
+
+static SourceLocation SourceLocationForType(QualType QT) {
+ SourceLocation Loc;
+ const Type *T = QT->getUnqualifiedDesugaredType();
+ if (const TagType *TT = dyn_cast<TagType>(T))
+ Loc = TT->getDecl()->getLocation();
+ else if (const ObjCInterfaceType *ObjCIT = dyn_cast<ObjCInterfaceType>(T))
+ Loc = ObjCIT->getDecl()->getLocation();
+ return Loc;
+}
+
+static bool CheckSYCLKernelName(Sema &S, SourceLocation Loc,
+ QualType KernelName) {
+ assert(!KernelName->isDependentType());
+
+ if (!KernelName->isStructureOrClassType()) {
+ // SYCL 2020 section 5.2, "Naming of kernels", only requires that the
+ // kernel name be a C++ typename. However, the definition of "kernel name"
+ // in the glossary states that a kernel name is a class type. Neither
+ // section explicitly states whether the kernel name type can be
+ // cv-qualified. For now, kernel name types are required to be class types
+ // and that they may be cv-qualified. The following issue requests
+ // clarification from the SYCL WG.
+ // https://github.com/KhronosGroup/SYCL-Docs/issues/568
+ S.Diag(Loc, diag::warn_sycl_kernel_name_not_a_class_type) << KernelName;
+ SourceLocation DeclTypeLoc = SourceLocationForType(KernelName);
+ if (DeclTypeLoc.isValid())
+ S.Diag(DeclTypeLoc, diag::note_entity_declared_at) << KernelName;
+ return true;
+ }
+
+ return false;
+}
+
+void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) {
+ // Ensure that all attributes present on the declaration are consistent
+ // and warn about any redundant ones.
+ const SYCLKernelEntryPointAttr *SKEPAttr = nullptr;
+ for (auto SAI = FD->specific_attr_begin<SYCLKernelEntryPointAttr>();
+ SAI != FD->specific_attr_end<SYCLKernelEntryPointAttr>(); ++SAI) {
+ if (!SKEPAttr) {
+ SKEPAttr = *SAI;
+ continue;
+ }
+ if (!getASTContext().hasSameType(SAI->getKernelName(),
+ SKEPAttr->getKernelName())) {
+ Diag(SAI->getLocation(), diag::err_sycl_entry_point_invalid_redeclaration)
+ << SAI->getKernelName() << SKEPAttr->getKernelName();
+ Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);
+ } else {
+ Diag(SAI->getLocation(),
+ diag::warn_sycl_entry_point_redundant_declaration);
+ Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);
+ }
+ }
+ assert(SKEPAttr && "Missing sycl_kernel_entry_point attribute");
+
+ // Ensure the kernel name type is valid.
+ if (!SKEPAttr->getKernelName()->isDependentType()) {
+ CheckSYCLKernelName(SemaRef, SKEPAttr->getLocation(),
+ SKEPAttr->getKernelName());
+ }
+
+ // Ensure that an attribute present on the previous declaration
+ // matches the one on this declaration.
+ FunctionDecl *PrevFD = FD->getPreviousDecl();
+ if (PrevFD && !PrevFD->isInvalidDecl()) {
+ const auto *PrevSKEPAttr = PrevFD->getAttr<SYCLKernelEntryPointAttr>();
+ if (PrevSKEPAttr) {
+ if (!getASTContext().hasSameType(SKEPAttr->getKernelName(),
+ PrevSKEPAttr->getKernelName())) {
+ Diag(SKEPAttr->getLocation(),
+ diag::err_sycl_entry_point_invalid_redeclaration)
+ << SKEPAttr->getKernelName() << PrevSKEPAttr->getKernelName();
+ Diag(PrevSKEPAttr->getLocation(), diag::note_previous_decl) << PrevFD;
+ }
+ }
+ }
+
+ if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (!MD->isStatic()) {
+ Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
+ << /*non-static member function*/ 0;
+ }
+ }
+ if (FD->isVariadic()) {
+ Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
+ << /*variadic function*/ 1;
+ }
+ if (FD->isConsteval()) {
+ Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
+ << /*consteval function*/ 5;
+ } else if (FD->isConstexpr()) {
+ Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
+ << /*constexpr function*/ 4;
+ }
+ if (FD->isNoReturn()) {
+ Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
+ << /*noreturn function*/ 6;
+ }
+
+ if (!FD->getReturnType()->isVoidType()) {
+ Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_return_type);
+ }
+
+ if (!FD->isInvalidDecl() && !FD->isTemplated()) {
----------------
tahonermann wrote:
@erichkeane, any further thoughts on this thread?
https://github.com/llvm/llvm-project/pull/120327
More information about the cfe-commits
mailing list