diff --git a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def index 9b270682f8cf0..cdf0804680ad0 100644 --- a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def +++ b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def @@ -112,6 +112,9 @@ FIELD(HasVariantMembers, 1, NO_MERGE) /// True if there no non-field members declared by the user. FIELD(HasOnlyCMembers, 1, NO_MERGE) +/// True if there is an '__init' method defined by the user. +FIELD(HasInitMethod, 1, NO_MERGE) + /// True if any field has an in-class initializer, including those /// within anonymous unions or structs. FIELD(HasInClassInitializer, 1, NO_MERGE) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index b54e6b0ac2171..2833df0505dac 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1139,6 +1139,9 @@ class CXXRecordDecl : public RecordDecl { /// \note This does NOT include a check for union-ness. bool isEmpty() const { return data().Empty; } + void setInitMethod(bool Val) { data().HasInitMethod = Val; } + bool hasInitMethod() const { return data().HasInitMethod; } + bool hasPrivateFields() const { return data().HasPrivateFields; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 17319c34f27b6..51be4d834c6b0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11493,6 +11493,10 @@ def warn_sycl_kernel_return_type : Warning< "function template with 'sycl_kernel' attribute must have a 'void' return type">, InGroup; +def err_sycl_special_type_num_init_method : Error< + "types with 'sycl_special_class' attribute must have one and only one '__init' " + "method defined">; + def err_bit_int_bad_size : Error<"%select{signed|unsigned}0 _BitInt must " "have a bit size of at least %select{2|1}0">; def err_bit_int_max_size : Error<"%select{signed|unsigned}0 _BitInt of bit " diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 108113274b8e0..187680a4ef1f9 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -81,8 +81,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false), HasOnlyCMembers(true), HasInClassInitializer(false), HasUninitializedReferenceMember(false), HasUninitializedFields(false), - HasInheritedConstructor(false), - HasInheritedDefaultConstructor(false), + HasInheritedConstructor(false), HasInheritedDefaultConstructor(false), HasInheritedAssignment(false), NeedOverloadResolutionForCopyConstructor(false), NeedOverloadResolutionForMoveConstructor(false), @@ -111,7 +110,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) HasDeclaredCopyAssignmentWithConstParam(false), IsAnyDestructorNoReturn(false), IsLambda(false), IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false), - HasODRHash(false), Definition(D) {} + HasODRHash(false), Definition(D), HasInitMethod(false) {} CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { return Bases.get(Definition->getASTContext().getExternalSource()); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b997024bcda20..f3cca82e60e02 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9194,6 +9194,13 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_in_union); NewFD->setInvalidDecl(); } + if ((Parent->isClass() || Parent->isStruct()) && + Parent->hasAttr() && + NewFD->getKind() == Decl::Kind::CXXMethod && NewFD->getIdentifier() && + NewFD->getName() == "__init" && D.isFunctionDefinition()) { + if (auto *Def = Parent->getDefinition()) + Def->setInitMethod(true); + } } SetNestedNameSpecifier(*this, NewFD, D); @@ -16764,8 +16771,21 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, RD->completeDefinition(); } - if (isa(Tag)) { + if (auto *RD = dyn_cast(Tag)) { FieldCollector->FinishClass(); + if (RD->hasAttr() && getLangOpts().SYCLIsDevice) { + auto *Def = RD->getDefinition(); + assert(Def && "The record is expected to have a completed definition"); + unsigned NumInitMethods = 0; + for (auto *Method : Def->methods()) { + if (!Method->getIdentifier()) + continue; + if (Method->getName() == "__init") + NumInitMethods++; + } + if (NumInitMethods > 1 || !Def->hasInitMethod()) + Diag(RD->getLocation(), diag::err_sycl_special_type_num_init_method); + } } // Exit this scope of this tag's definition. diff --git a/sycl/include/CL/sycl/accessor.hpp b/sycl/include/CL/sycl/accessor.hpp index ba2f5e15f373a..cf13264b4fca0 100644 --- a/sycl/include/CL/sycl/accessor.hpp +++ b/sycl/include/CL/sycl/accessor.hpp @@ -2200,8 +2200,8 @@ class __SYCL_SPECIAL_CLASS accessor -class __SYCL_SPECIAL_CLASS accessor +class accessor : public detail::image_accessor { public: