[OpenCL] Prohibit using reserve_id_t in program scope.

Patch by Egor Churaev (echuraev).

Reviewers: Anastasia

Subscribers: cfe-commits, yaxunl, bader

Differential Revision: https://reviews.llvm.org/D27099

llvm-svn: 288126
This commit is contained in:
Alexey Bader 2016-11-29 10:21:40 +00:00
parent bba2d59ea4
commit c211c6c884
5 changed files with 70 additions and 54 deletions

View File

@ -8075,8 +8075,6 @@ def note_within_field_of_type : Note<
"within field of type %0 declared here">;
def note_illegal_field_declared_here : Note<
"field of illegal %select{type|pointer type}0 %1 declared here">;
def err_event_t_global_var : Error<
"the event_t type cannot be used to declare a program scope variable">;
def err_opencl_type_struct_or_union_field : Error<
"the %0 type cannot be used to declare a structure or union field">;
def err_event_t_addr_space_qual : Error<
@ -8589,6 +8587,8 @@ def note_related_result_type_inferred : Note<
def note_related_result_type_explicit : Note<
"%select{overridden|current}0 method is explicitly declared 'instancetype'"
"%select{| and is expected to return an instance of its class type}0">;
def err_invalid_type_for_program_scope_var : Error<
"the %0 type cannot be used to declare a program scope variable">;
}

View File

@ -5909,32 +5909,31 @@ NamedDecl *Sema::ActOnVariableDeclarator(
return nullptr;
}
// OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
// OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
// argument.
if (getLangOpts().OpenCL && (R->isImageType() || R->isPipeType())) {
Diag(D.getIdentifierLoc(),
diag::err_opencl_type_can_only_be_used_as_function_parameter)
<< R;
D.setInvalidType();
return nullptr;
}
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
// dllimport globals without explicit storage class are treated as extern. We
// have to change the storage class this early to get the right DeclContext.
if (SC == SC_None && !DC->isRecord() &&
hasParsedAttr(S, D, AttributeList::AT_DLLImport) &&
!hasParsedAttr(S, D, AttributeList::AT_DLLExport))
SC = SC_Extern;
DeclContext *OriginalDC = DC;
bool IsLocalExternDecl = SC == SC_Extern &&
adjustContextForLocalExternDecl(DC);
if (getLangOpts().OpenCL) {
// OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
// OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
// argument.
if (R->isImageType() || R->isPipeType()) {
Diag(D.getIdentifierLoc(),
diag::err_opencl_type_can_only_be_used_as_function_parameter)
<< R;
D.setInvalidType();
return nullptr;
}
// OpenCL v1.2 s6.9.r:
// The event type cannot be used to declare a program scope variable.
// OpenCL v2.0 s6.9.q:
// The clk_event_t and reserve_id_t types cannot be declared in program scope.
if (NULL == S->getParent()) {
if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) {
Diag(D.getIdentifierLoc(),
diag::err_invalid_type_for_program_scope_var) << R;
D.setInvalidType();
return nullptr;
}
}
// OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
QualType NR = R;
while (NR->isPointerType()) {
@ -5954,8 +5953,40 @@ NamedDecl *Sema::ActOnVariableDeclarator(
D.setInvalidType();
}
}
// OpenCL v1.2 s6.9.b p4:
// The sampler type cannot be used with the __local and __global address
// space qualifiers.
if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local ||
R.getAddressSpace() == LangAS::opencl_global)) {
Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
}
// OpenCL v1.2 s6.9.r:
// The event type cannot be used with the __local, __constant and __global
// address space qualifiers.
if (R->isEventT()) {
if (R.getAddressSpace()) {
Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
D.setInvalidType();
}
}
}
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
// dllimport globals without explicit storage class are treated as extern. We
// have to change the storage class this early to get the right DeclContext.
if (SC == SC_None && !DC->isRecord() &&
hasParsedAttr(S, D, AttributeList::AT_DLLImport) &&
!hasParsedAttr(S, D, AttributeList::AT_DLLExport))
SC = SC_Extern;
DeclContext *OriginalDC = DC;
bool IsLocalExternDecl = SC == SC_Extern &&
adjustContextForLocalExternDecl(DC);
if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
@ -5988,32 +6019,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
if (getLangOpts().OpenCL) {
// OpenCL v1.2 s6.9.b p4:
// The sampler type cannot be used with the __local and __global address
// space qualifiers.
if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local ||
R.getAddressSpace() == LangAS::opencl_global)) {
Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
}
// OpenCL 1.2 spec, p6.9 r:
// The event type cannot be used to declare a program scope variable.
// The event type cannot be used with the __local, __constant and __global
// address space qualifiers.
if (R->isEventT()) {
if (S->getParent() == nullptr) {
Diag(D.getLocStart(), diag::err_event_t_global_var);
D.setInvalidType();
}
if (R.getAddressSpace()) {
Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
D.setInvalidType();
}
}
}
bool IsExplicitSpecialization = false;
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
event_t glb_evt; // expected-error {{the event_t type cannot be used to declare a program scope variable}}
event_t glb_evt; // expected-error {{the 'event_t' type cannot be used to declare a program scope variable}}
constant struct evt_s {
event_t evt; // expected-error {{the 'event_t' type cannot be used to declare a structure or union field}}

View File

@ -0,0 +1,3 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
global clk_event_t ce; // expected-error {{the '__global clk_event_t' type cannot be used to declare a program scope variable}}

View File

@ -1,5 +1,8 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
global pipe int gp; // expected-error {{type '__global read_only pipe int' can only be used as a function parameter in OpenCL}}
global reserve_id_t rid; // expected-error {{the '__global reserve_id_t' type cannot be used to declare a program scope variable}}
void test1(pipe int *p) {// expected-error {{pipes packet types cannot be of reference type}}
}
void test2(pipe p) {// expected-error {{missing actual type specifier for pipe}}
@ -20,3 +23,8 @@ void test5(pipe int p) {
typedef pipe int pipe_int_t;
pipe_int_t test6() {} // expected-error{{declaring function return value of type 'pipe_int_t' (aka 'read_only pipe int') is not allowed}}
bool test_id_comprision(void) {
reserve_id_t id1, id2;
return (id1 == id2); // expected-error {{invalid operands to binary expression ('reserve_id_t' and 'reserve_id_t')}}
}