diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6726,17 +6726,20 @@ llvm_unreachable("Unknown type of decl!"); } + /// Returns true if there hasn't been any invalid type diagnosed. -static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D, - DeclContext *DC, QualType R) { +static bool diagnoseOpenCLTypes(Sema &Se, VarDecl *NewVD) { + DeclContext *DC = NewVD->getDeclContext(); + QualType R = NewVD->getType(); + // 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()) { - Se.Diag(D.getIdentifierLoc(), + Se.Diag(NewVD->getLocation(), diag::err_opencl_type_can_only_be_used_as_function_parameter) << R; - D.setInvalidType(); + NewVD->setInvalidDecl(); return false; } @@ -6745,12 +6748,12 @@ // 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 (NewVD->hasGlobalStorage() && !NewVD->isStaticLocal()) { if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) { - Se.Diag(D.getIdentifierLoc(), + Se.Diag(NewVD->getLocation(), diag::err_invalid_type_for_program_scope_var) << R; - D.setInvalidType(); + NewVD->setInvalidDecl(); return false; } } @@ -6763,9 +6766,9 @@ NR->isReferenceType()) { if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType() || NR->isFunctionReferenceType()) { - Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer) + Se.Diag(NewVD->getLocation(), diag::err_opencl_function_pointer) << NR->isReferenceType(); - D.setInvalidType(); + NewVD->setInvalidDecl(); return false; } NR = NR->getPointeeType(); @@ -6777,8 +6780,8 @@ // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and // half array type (unless the cl_khr_fp16 extension is enabled). if (Se.Context.getBaseElementType(R)->isHalfType()) { - Se.Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R; - D.setInvalidType(); + Se.Diag(NewVD->getLocation(), diag::err_opencl_half_declaration) << R; + NewVD->setInvalidDecl(); return false; } } @@ -6788,34 +6791,20 @@ // address space qualifiers. if (R->isEventT()) { if (R.getAddressSpace() != LangAS::opencl_private) { - Se.Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual); - D.setInvalidType(); + Se.Diag(NewVD->getBeginLoc(), diag::err_event_t_addr_space_qual); + NewVD->setInvalidDecl(); return false; } } - // C++ for OpenCL does not allow the thread_local storage qualifier. - // OpenCL C does not support thread_local either, and - // also reject all other thread storage class specifiers. - DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec(); - if (TSC != TSCS_unspecified) { - bool IsCXX = Se.getLangOpts().OpenCLCPlusPlus; - Se.Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), - diag::err_opencl_unknown_type_specifier) - << IsCXX << Se.getLangOpts().getOpenCLVersionTuple().getAsString() - << DeclSpec::getSpecifierName(TSC) << 1; - D.setInvalidType(); - return false; - } - if (R->isSamplerT()) { // OpenCL v1.2 s6.9.b p4: // The sampler type cannot be used with the __local and __global address // space qualifiers. if (R.getAddressSpace() == LangAS::opencl_local || R.getAddressSpace() == LangAS::opencl_global) { - Se.Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace); - D.setInvalidType(); + Se.Diag(NewVD->getLocation(), diag::err_wrong_sampler_addressspace); + NewVD->setInvalidDecl(); } // OpenCL v1.2 s6.12.14.1: @@ -6824,12 +6813,13 @@ if (DC->isTranslationUnit() && !(R.getAddressSpace() == LangAS::opencl_constant || R.isConstQualified())) { - Se.Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler); - D.setInvalidType(); + Se.Diag(NewVD->getLocation(), diag::err_opencl_nonconst_global_sampler); + NewVD->setInvalidDecl(); } - if (D.isInvalidType()) + if (NewVD->isInvalidDecl()) return false; } + return true; } @@ -7256,10 +7246,17 @@ } if (getLangOpts().OpenCL) { - deduceOpenCLAddressSpace(NewVD); - diagnoseOpenCLTypes(S, *this, D, DC, NewVD->getType()); + DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec(); + if (TSC != TSCS_unspecified) { + bool IsCXX = getLangOpts().OpenCLCPlusPlus; + Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), + diag::err_opencl_unknown_type_specifier) + << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString() + << DeclSpec::getSpecifierName(TSC) << 1; + NewVD->setInvalidDecl(); + } } // Handle attributes prior to checking for duplicates in MergeVarDecl @@ -7923,6 +7920,9 @@ } if (getLangOpts().OpenCL) { + if (!diagnoseOpenCLTypes(*this, NewVD)) + return; + // OpenCL v2.0 s6.12.5 - The __block storage type is not supported. if (NewVD->hasAttr()) { Diag(NewVD->getLocation(), diag::err_opencl_block_storage_type); @@ -7944,6 +7944,7 @@ return; } } + // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the // __constant address space. // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static diff --git a/clang/test/SemaOpenCL/clk_event_t.cl b/clang/test/SemaOpenCL/clk_event_t.cl --- a/clang/test/SemaOpenCL/clk_event_t.cl +++ b/clang/test/SemaOpenCL/clk_event_t.cl @@ -12,6 +12,9 @@ clk_event_t ce2; clk_event_t ce3 = CLK_NULL_EVENT; + // FIXME: Not obvious if this should give an error as if it was in program scope. + static clk_event_t ce4; + if (e == ce1) { // expected-error {{invalid operands to binary expression ('__private event_t' and '__private clk_event_t')}} return 9; } diff --git a/clang/test/SemaOpenCL/event_t.cl b/clang/test/SemaOpenCL/event_t.cl --- a/clang/test/SemaOpenCL/event_t.cl +++ b/clang/test/SemaOpenCL/event_t.cl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}} expected-error{{program scope variable must reside in constant address space}} +event_t glb_evt; // expected-error {{the '__private 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}} @@ -10,7 +10,7 @@ void kernel ker(event_t argevt) { // expected-error {{'__private event_t' cannot be used as the type of a kernel parameter}} event_t e; - constant event_t const_evt; // expected-error {{the event_t type can only be used with __private address space qualifier}} expected-error{{variable in constant address space must be initialized}} + constant event_t const_evt; // expected-error{{the '__constant event_t' type cannot be used to declare a program scope variable}} foo(e); foo(0); foo(5); // expected-error {{passing 'int' to parameter of incompatible type 'event_t'}} diff --git a/clang/test/SemaOpenCL/sampler_t.cl b/clang/test/SemaOpenCL/sampler_t.cl --- a/clang/test/SemaOpenCL/sampler_t.cl +++ b/clang/test/SemaOpenCL/sampler_t.cl @@ -48,9 +48,6 @@ sampler_t bad(void); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}} sampler_t global_nonconst_smp = 0; // expected-error {{global sampler requires a const or constant address space qualifier}} -#ifdef CHECK_SAMPLER_VALUE -// expected-warning@-2{{sampler initializer has invalid Filter Mode bits}} -#endif const sampler_t glb_smp10 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; const constant sampler_t glb_smp11 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; diff --git a/clang/test/SemaOpenCLCXX/template-opencl-types.clcpp b/clang/test/SemaOpenCLCXX/template-opencl-types.clcpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaOpenCLCXX/template-opencl-types.clcpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only + +template +T global_variable; // expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}} + +clk_event_t global_event; // expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}} + +template +void templ() { + T loc; + // expected-error@-1{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}} + // expected-error@-2{{declaring variable of type '__private half' is not allowed}} + // expected-error@-3{{the event_t type can only be used with __private address space qualifier}} +} + +void foo() { + templ(); // expected-note{{in instantiation of function template specialization 'templ<__read_only image1d_t>' requested here}} + templ(); // expected-note{{in instantiation of function template specialization 'templ' requested here}} + templ<__local event_t>(); // expected-note{{in instantiation of function template specialization 'templ<__local event_t>' requested here}} + + image1d_t img; // expected-error{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}} + half h; // expected-error{{declaring variable of type '__private half' is not allowed}} + __local event_t e; // expected-error{{the event_t type can only be used with __private address space qualifier}} + + (void) global_variable; // expected-note{{in instantiation of variable template specialization 'global_variable' requested here}} +}