zahiraam updated this revision to Diff 393278.
zahiraam marked an inline comment as done.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D114483/new/
https://reviews.llvm.org/D114483
Files:
clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
clang/include/clang/AST/DeclCXX.h
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/DeclCXX.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/Misc/pragma-attribute-supported-attributes-list.test
clang/test/SemaSYCL/special-class-attribute-on-non-sycl.cpp
clang/test/SemaSYCL/special-class-attribute.cpp
Index: clang/test/SemaSYCL/special-class-attribute.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaSYCL/special-class-attribute.cpp
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fsycl-is-device -verify %s
+
+// No diagnostics
+class [[clang::sycl_special_class]] class1 {
+ void __init() {};
+};
+class __attribute__((sycl_special_class)) class2 {
+ void __init() {};
+};
+
+class class3;
+class [[clang::sycl_special_class]] class3 {
+ void __init() {};
+};
+
+class class4;
+class __attribute__((sycl_special_class)) class4 {
+ void __init() {};
+};
+
+class [[clang::sycl_special_class]] struct1 {
+ void __init() {};
+};
+struct __attribute__((sycl_special_class)) struct2 {
+ void __init() {};
+};
+
+class [[clang::sycl_special_class]] class5 {
+ void __init() {};
+};
+class special5 {};
+
+class __attribute__((sycl_special_class)) class6;
+class class6 {
+ void __init() {};
+};
+
+
+// Must have __init method defined
+class __attribute__((sycl_special_class)) class7 { // expected-error {{types with 'sycl_special_class' attribute must have an '__init' method defined}}
+ class7() {}
+};
+class [[clang::sycl_special_class]] class8 { // expected-error {{types with 'sycl_special_class' attribute must have an '__init' method defined}}
+ void __init();
+};
+
+struct __attribute__((sycl_special_class)) struct3;
+struct struct3 {}; // expected-error {{types with 'sycl_special_class' attribute must have an '__init' method defined}}
+
+
+// Only classes
+[[clang::sycl_special_class]] int var1 = 0; // expected-warning {{'sycl_special_class' attribute only applies to classes}}
+__attribute__((sycl_special_class)) int var2 = 0; // expected-warning {{'sycl_special_class' attribute only applies to classes}}
+
+[[clang::sycl_special_class]] void foo1(); // expected-warning {{'sycl_special_class' attribute only applies to classes}}
+__attribute__((sycl_special_class)) void foo2(); // expected-warning {{'sycl_special_class' attribute only applies to classes}}
+
+// Attribute takes no arguments
+class [[clang::sycl_special_class(1)]] class9 {}; // expected-error {{'sycl_special_class' attribute takes no arguments}}
+class __attribute__((sycl_special_class(1))) class10 {}; // expected-error {{'sycl_special_class' attribute takes no arguments}}
Index: clang/test/SemaSYCL/special-class-attribute-on-non-sycl.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaSYCL/special-class-attribute-on-non-sycl.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fsycl-is-device -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -x c++ %s
+
+#ifndef __SYCL_DEVICE_ONLY__
+// expected-warning@+5 {{'sycl_special_class' attribute ignored}}
+#else
+// expected-no-diagnostics
+#endif
+
+class __attribute__((sycl_special_class)) special_class {
+ void __init() {};
+};
+
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -154,6 +154,7 @@
// CHECK-NEXT: ReturnTypestate (SubjectMatchRule_function, SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function)
// CHECK-NEXT: ReturnsTwice (SubjectMatchRule_function)
+// CHECK-NEXT: SYCLSpecialClass (SubjectMatchRule_record)
// CHECK-NEXT: ScopedLockable (SubjectMatchRule_record)
// CHECK-NEXT: Section (SubjectMatchRule_function, SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property)
// CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member)
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -7757,6 +7757,13 @@
handleSimpleAttribute<SYCLKernelAttr>(S, D, AL);
}
+static void handleSYCLSpecialClassAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ // The 'sycl_special_class' attribute applies only to records.
+ const auto *RD = cast<CXXRecordDecl>(D);
+ assert(RD && "Record type is expected");
+ handleSimpleAttribute<SYCLSpecialClassAttr>(S, D, AL);
+}
+
static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) {
if (!cast<VarDecl>(D)->hasGlobalStorage()) {
S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var)
@@ -8180,6 +8187,9 @@
case ParsedAttr::AT_SYCLKernel:
handleSYCLKernelAttr(S, D, AL);
break;
+ case ParsedAttr::AT_SYCLSpecialClass:
+ handleSYCLSpecialClassAttr(S, D, AL);
+ break;
case ParsedAttr::AT_Format:
handleFormatAttr(S, D, AL);
break;
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -9112,6 +9112,13 @@
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_in_union);
NewFD->setInvalidDecl();
}
+ if ((Parent->isClass() || Parent->isStruct()) &&
+ Parent->hasAttr<SYCLSpecialClassAttr>() &&
+ NewFD->getKind() == Decl::Kind::CXXMethod &&
+ NewFD->getName() == "__init" && D.isFunctionDefinition()) {
+ if (auto *def = Parent->getDefinition())
+ def->SetInitMethod(true);
+ }
}
SetNestedNameSpecifier(*this, NewFD, D);
@@ -16665,8 +16672,13 @@
RD->completeDefinition();
}
- if (isa<CXXRecordDecl>(Tag)) {
+ if (auto *RD = dyn_cast<CXXRecordDecl>(Tag)) {
FieldCollector->FinishClass();
+ if (RD->hasAttr<SYCLSpecialClassAttr>()) {
+ auto *def = RD->getDefinition();
+ if (def && !def->hasInitMethod())
+ Diag(RD->getLocation(), diag::err_sycl_special_type_missing_init_method);
+ }
}
// Exit this scope of this tag's definition.
Index: clang/lib/AST/DeclCXX.cpp
===================================================================
--- clang/lib/AST/DeclCXX.cpp
+++ clang/lib/AST/DeclCXX.cpp
@@ -111,7 +111,7 @@
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());
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11425,6 +11425,8 @@
def warn_sycl_kernel_return_type : Warning<
"function template with 'sycl_kernel' attribute must have a 'void' return type">,
InGroup<IgnoredAttributes>;
+def err_sycl_special_type_missing_init_method : Error<
+ "types with 'sycl_special_class' attribute must have an '__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">;
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -409,6 +409,67 @@
}];
}
+def SYCLSpecialClassDocs : Documentation {
+ let Category = DocCatStmt;
+ let Content = [{
+SYCL defines some special classes (accessor, sampler and stream) that require
+specific handling during the generation of SPIR entry point.
+The ``__attribute__((sycl_special_class))`` attribute is used in SYCL
+headers to indicate that a class or a struct needs a specific handling when
+it is passed from host to device.
+Special classes/struct will have a mandatory __init method and an optional __finalize
+method (__finalize method method is used only with stream type). __init method gives the
+user additional information required. For instance, the kernel function arguments
+list is derived from the arguments of the __init method. The arguments of the __init method
+are copied into the kernel function argument list and __init and __finalize methods are called
+at the beginning and the end of the kernel, respectively.
+Please note that this is an attribute that is used for internal implementation and not intended
+to be used by external users.
+
+The sntax of the attribute is as follows:
+
+.. code-block:: c++
+
+ class __attribute__((sycl_special_class)) accessor {};
+ class [[clang::sycl_special_class]] accessor {};
+
+This is a code example that illustrates the use of the attribute:
+
+.. code-block:: c++
+
+ class __attribute__((sycl_special_class)) SpecialType {
+ int F1;
+ int F2;
+ void __init(int f1) {
+ F1 = f1;
+ F2 = f1;
+ }
+ void __finalize() {}
+ public:
+ SpecialType() = default;
+ int getF2() const { return F2; }
+ };
+
+ int main () {
+ SpecialType T;
+ cgh.single_task([=]() {
+ T.getF2();
+ });
+}
+
+This would trigger the following kernel entry point in the AST:
+
+.. code-block:: c++
+
+ void __sycl_kernel(int f1) {
+ SpecialType T;
+ T.__init(f1);
+ ...
+ T.__finalize()
+ }
+ }];
+}
+
def C11NoReturnDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1191,6 +1191,13 @@
let Documentation = [SYCLKernelDocs];
}
+def SYCLSpecialClass: InheritableAttr {
+ let Spellings = [Clang<"sycl_special_class">];
+ let Subjects = SubjectList<[CXXRecord]>;
+ let LangOpts = [SYCL];
+ let Documentation = [SYCLSpecialClassDocs];
+}
+
def C11NoReturn : InheritableAttr {
let Spellings = [Keyword<"_Noreturn">];
let Subjects = SubjectList<[Function], ErrorDiag>;
Index: clang/include/clang/AST/DeclCXX.h
===================================================================
--- clang/include/clang/AST/DeclCXX.h
+++ clang/include/clang/AST/DeclCXX.h
@@ -1140,6 +1140,9 @@
/// \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;
}
Index: clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
===================================================================
--- clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
+++ clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
@@ -112,6 +112,9 @@
/// 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)
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits