Skip to content

[SYCL] Add the remaining diagnostics to device_global implementation #5810

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1eaf97d
More diagnostic work
schittir Mar 15, 2022
8481087
Merge remote-tracking branch 'intel_llvm_remote/sycl' into device_glo…
schittir Mar 27, 2022
d472f02
Merge remote-tracking branch 'intel_llvm_remote/sycl' into device_glo…
schittir Mar 29, 2022
8e7011a
Fix typo
schittir Mar 29, 2022
03d63d0
Merge remote-tracking branch 'intel_llvm_remote/sycl' into device_glo…
schittir Apr 19, 2022
56ab01d
device_global inside a method
schittir Apr 21, 2022
f28af3e
Fix format and add test cases
schittir Apr 22, 2022
f1412c2
Fix format
schittir Apr 22, 2022
6155a23
Add TODO cases
schittir May 10, 2022
9a53449
Fix format, address comments
schittir May 10, 2022
0b529a2
Address some comments
schittir Jun 15, 2022
cbdfe33
Fix lint
schittir Jun 15, 2022
58db09e
Lint again
schittir Jun 15, 2022
1c3ef52
Address more comments
schittir Jul 8, 2022
f183565
Fix bug in diagnosing private device_global
schittir Aug 10, 2022
faeb23d
Remove wrong diagnostic
schittir Aug 11, 2022
36fc259
Change error message and move call to add vardecl
schittir Aug 14, 2022
9fefb21
Fix failing case and change the error message
schittir Aug 15, 2022
ec196b5
Add check for global_variable_allowed attribute
schittir Aug 15, 2022
f89b641
Attempting to fix test conflict
schittir Aug 15, 2022
9b8893e
Added separate structure for type decorated with global_variable_allowed
schittir Aug 15, 2022
15dd595
Remove needless type and check for global_variable_allowed
schittir Aug 16, 2022
7b120e5
Merge remote-tracking branch 'intel_llvm_remote/sycl' into device_glo…
schittir Aug 16, 2022
736c0ee
Remove cl:: from test case
schittir Aug 16, 2022
9f1e649
Add diagnostic for device_global array and change comment in test
schittir Aug 19, 2022
6fd721b
Simplify array element type checking per comments
schittir Aug 19, 2022
48cf937
Merge remote-tracking branch 'intel_llvm_remote/sycl' into device_glo…
schittir Aug 23, 2022
9874230
Address code-style comments
schittir Aug 23, 2022
6092803
Add diagnostic for private var and testcase for template class
schittir Aug 23, 2022
c522f53
Check that diagnostics are emitted when function is instantiated
schittir Aug 23, 2022
8a01ce7
Remove return nullptr to diagnose properly
schittir Aug 24, 2022
35e6208
Add instantiation call for templFoo()
schittir Aug 25, 2022
153a5eb
Drop Var->isLocalVarDeclOrParm() check; add Var->getAccess()!= AS_public
schittir Aug 26, 2022
1c19715
Remove templFoo<int> specialization case
schittir Aug 26, 2022
f398bfb
Diagnose when device_global is a protected member of a class
schittir Aug 26, 2022
f45a351
Remove space for uniformity
schittir Aug 26, 2022
0377ef9
Change check for protected device_global members
schittir Aug 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -7219,9 +7219,11 @@ def warn_format_nonliteral : Warning<
InGroup<FormatNonLiteral>, DefaultIgnore;

def err_sycl_device_global_incorrect_scope : Error<
"'device_global' variables must be static or declared at namespace scope">;
"'device_global' variable must be a static data member or declared in global or namespace scope">;
def err_sycl_device_global_not_publicly_accessible: Error<
"'device_global' member variable %0 is not publicly accessible from namespace scope">;
"'device_global' member variable %0 should be publicly accessible from namespace scope">;
def err_sycl_device_global_array : Error<
"'device_global' array is not allowed">;

def err_unexpected_interface : Error<
"unexpected interface name %0: expected expression">;
Expand Down
31 changes: 25 additions & 6 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7678,13 +7678,32 @@ NamedDecl *Sema::ActOnVariableDeclarator(
NewVD->setTSCSpec(TSCS);
}

// Global variables with types decorated with device_global attribute must be
// static if they are declared in SYCL device code.
if (getLangOpts().SYCLIsDevice) {
if (SCSpec != DeclSpec::SCS_static && !NewVD->hasGlobalStorage() &&
isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
NewVD->getType()))
Diag(D.getIdentifierLoc(), diag::err_sycl_device_global_incorrect_scope);
// device_global array is not allowed.
if (const ArrayType *AT = getASTContext().getAsArrayType(NewVD->getType()))
if (isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
AT->getElementType()))
Diag(NewVD->getLocation(), diag::err_sycl_device_global_array);

// Global variables with types decorated with device_global attribute must
// be static if they are declared in SYCL device code.
if (isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
NewVD->getType())) {
if (SCSpec == DeclSpec::SCS_static) {
const DeclContext *DC = NewVD->getDeclContext();
while (!DC->isTranslationUnit()) {
if (isa<FunctionDecl>(DC)) {
Diag(D.getIdentifierLoc(),
diag::err_sycl_device_global_incorrect_scope);
break;
}
DC = DC->getParent();
}
} else if (!NewVD->hasGlobalStorage()) {
Diag(D.getIdentifierLoc(),
diag::err_sycl_device_global_incorrect_scope);
}
}

// Static variables declared inside SYCL device code must be const or
// constexpr unless their types are decorated with global_variable_allowed
Expand Down
22 changes: 18 additions & 4 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3598,10 +3598,24 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (getLangOpts().SYCLIsDevice) {
if (auto Value = dyn_cast<ValueDecl>(Member)) {
if (isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
Value->getType()) &&
Value->getAccess() != AS_public) {
Diag(Loc, diag::err_sycl_device_global_not_publicly_accessible)
<< Value;
Value->getType())) {
if (Value->getAccess() == AS_private ||
Value->getAccess() == AS_protected) {
Diag(Loc, diag::err_sycl_device_global_not_publicly_accessible)
<< Value;
}
const DeclContext *DC = Member->getDeclContext();
while (!DC->isTranslationUnit()) {
if (auto Decl = dyn_cast<NamedDecl>(DC)) {
if (Decl->getAccess() == AS_private ||
Decl->getAccess() == AS_protected) {
Diag(Loc, diag::err_sycl_device_global_not_publicly_accessible)
<< Value;
break;
}
}
DC = DC->getParent();
}
}
}
}
Expand Down
37 changes: 36 additions & 1 deletion clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1614,14 +1614,38 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
// Only add this if we aren't instantiating a variable template. We'll end up
// adding the VarTemplateSpecializationDecl later.
if (!InstantiatingVarTemplate) {
SemaRef.addSyclVarDecl(Var);
if (SemaRef.getLangOpts().SYCLIsDevice &&
SemaRef.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
Var->getType())) {
if (!Var->hasGlobalStorage())
SemaRef.Diag(D->getLocation(),
diag::err_sycl_device_global_incorrect_scope);

if (Var->getAccess() == AS_private || Var->getAccess() == AS_protected)
SemaRef.Diag(D->getLocation(),
diag::err_sycl_device_global_not_publicly_accessible)
<< Var;

if (Var->isStaticLocal()) {
const DeclContext *DC = Var->getDeclContext();
while (!DC->isTranslationUnit()) {
if (isa<FunctionDecl>(DC)) {
SemaRef.Diag(D->getLocation(),
diag::err_sycl_device_global_incorrect_scope);
break;
}
DC = DC->getParent();
}
}
}
if (const auto *SYCLDevice = Var->getAttr<SYCLDeviceAttr>()) {
if (!SemaRef.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
Var->getType()))
SemaRef.Diag(SYCLDevice->getLoc(),
diag::err_sycl_attribute_not_device_global)
<< SYCLDevice;
}
SemaRef.addSyclVarDecl(Var);
}
return Var;
}
Expand Down Expand Up @@ -1711,6 +1735,17 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {

Field->setImplicit(D->isImplicit());
Field->setAccess(D->getAccess());
// Static members are not processed here, so error out if we have a device
// global without checking access modifier.
if (SemaRef.getLangOpts().SYCLIsDevice) {
if (SemaRef.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
Field->getType())) {
SemaRef.Diag(D->getLocation(),
diag::err_sycl_device_global_incorrect_scope);
Field->setInvalidDecl();
return nullptr;
}
}
Owner->addDecl(Field);

return Field;
Expand Down
101 changes: 90 additions & 11 deletions clang/test/SemaSYCL/device_global.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// RUN: %clang_cc1 -fsycl-is-device -std=c++17 -sycl-std=2020 -verify %s
#include "Inputs/sycl.hpp"

// Test cases below check for valid usage of device_global and
// global_variable_allowed attributes, and that they are being correctly
// generated in the AST.
// Diagnostic tests for device_global and global_variable_allowed attribute.

// Test that there are no errors when variables of type device_global are
// decorated with global_variable_allowed attribute appropriately.
using namespace sycl::ext::oneapi;

device_global<int> glob; // OK
Expand All @@ -18,19 +19,95 @@ device_global<char> Foo::d;

struct Baz {
private:
// expected-error@+1{{'device_global' member variable 'f' is not publicly accessible from namespace scope}}
// expected-error@+1{{'device_global' member variable 'f' should be publicly accessible from namespace scope}}
static device_global<int> f;

protected:
// expected-error@+1{{'device_global' member variable 'g' should be publicly accessible from namespace scope}}
static device_global<int> g;
};

device_global<int> Baz::f;

device_global<int[4]> not_array; // OK

// expected-error@+1{{'device_global' array is not allowed}}
device_global<int> array[4];

device_global<int> same_name; // OK

namespace foo {
device_global<int> same_name; // OK
}
namespace {
device_global<int> same_name; // OK

struct BBar {
private:
struct BarInsider {
// expected-error@+1{{'device_global' member variable 'c' should be publicly accessible from namespace scope}}
static device_global<float> c;
};

protected:
struct BarInsiderProtected {
// expected-error@+1{{'device_global' member variable 'c' should be publicly accessible from namespace scope}}
static device_global<float> c;
};
};

struct ABar {
void method() {
// expected-error@+1{{'device_global' variable must be a static data member or declared in global or namespace scope}}
static device_global<float> c;
}
struct BarInsider {
static device_global<float> c;
void method() {
// expected-error@+1{{'device_global' variable must be a static data member or declared in global or namespace scope}}
static device_global<float> c;
}
};
};

template <typename T> void fooBar() {
// expected-error@+1{{'device_global' variable must be a static data member or declared in global or namespace scope}}
static device_global<T> c;
// expected-error@+1{{'device_global' variable must be a static data member or declared in global or namespace scope}}
device_global<T> d;
}

template <typename T> struct TS {
private:
// expected-error@+1 2{{'device_global' member variable 'a' should be publicly accessible from namespace scope}}
static device_global<T> a;
// expected-error@+1 2{{'device_global' variable must be a static data member or declared in global or namespace scope}}
device_global<T> b;
// expected-error@+2{{'device_global' member variable 'c' should be publicly accessible from namespace scope}}
// expected-error@+1 2{{'device_global' variable must be a static data member or declared in global or namespace scope}}
device_global<int> c;

public:
static device_global<T> d;
// expected-error@+1 2{{'device_global' variable must be a static data member or declared in global or namespace scope}}
device_global<T> e;
// expected-error@+1 2{{'device_global' variable must be a static data member or declared in global or namespace scope}}
device_global<int> f;

protected:
// expected-error@+1 2{{'device_global' member variable 'g' should be publicly accessible from namespace scope}}
static device_global<T> g;
// expected-error@+1 2{{'device_global' variable must be a static data member or declared in global or namespace scope}}
device_global<T> h;
// expected-error@+2{{'device_global' member variable 'i' should be publicly accessible from namespace scope}}
// expected-error@+1 2{{'device_global' variable must be a static data member or declared in global or namespace scope}}
device_global<int> i;
};

// expected-note@+1{{in instantiation of template class 'TS<int>' requested here}}
TS<int> AAAA;

//expected-note@+2{{in instantiation of template class 'TS<char>' requested here}}
template <typename T> void templFoo () {
TS<T> Var;
}

// expected-error@+2{{'device_global' attribute only applies to classes}}
Expand All @@ -44,6 +121,12 @@ device_global<int> same_name; // OK
union [[__sycl_detail__::device_global]] [[__sycl_detail__::global_variable_allowed]] a_union;

int main() {
// expected-note@+1{{in instantiation of function template specialization 'templFoo<char>' requested here}}
templFoo<char>();

// expected-note@+1{{in instantiation of function template specialization 'fooBar<int>' requested here}}
fooBar<int>();

sycl::kernel_single_task<class KernelName1>([=]() {
(void)glob;
(void)static_glob;
Expand All @@ -53,11 +136,7 @@ int main() {
});

sycl::kernel_single_task<class KernelName2>([]() {
// expected-error@+1{{'device_global' variables must be static or declared at namespace scope}}
// expected-error@+1{{'device_global' variable must be a static data member or declared in global or namespace scope}}
device_global<int> non_static;

// expect no error on non_const_static declaration if decorated with
// [[__sycl_detail__::global_variable_allowed]]
static device_global<int> non_const_static;
});
}