olestrohm updated this revision to Diff 339976. olestrohm added a comment. I noticed that I could move the new check above the diagnostic for program scope variables, and the check during parsing can then be removed, while maintaining good diagnostics.
This does change the diagnostic for `event_t` mentioned above, however it's not a bad diagnostic, and actually matches what happens in non-kernel functions, so I think it's okay. I would prefer the previous diagnostic for `event_t`, but that originates in the other branch of the same if statement as the program scope diagnostic, so it's not easy to separate them out and then insert the new check between them. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D100860/new/ https://reviews.llvm.org/D100860 Files: clang/lib/Sema/SemaDecl.cpp clang/test/SemaOpenCL/clk_event_t.cl clang/test/SemaOpenCL/event_t.cl clang/test/SemaOpenCL/sampler_t.cl clang/test/SemaOpenCLCXX/template-opencl-types.clcpp
Index: clang/test/SemaOpenCLCXX/template-opencl-types.clcpp =================================================================== --- /dev/null +++ clang/test/SemaOpenCLCXX/template-opencl-types.clcpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only + +template<typename T> +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<typename T> +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<image1d_t>(); // expected-note{{in instantiation of function template specialization 'templ<__read_only image1d_t>' requested here}} + templ<half>(); // expected-note{{in instantiation of function template specialization 'templ<half>' 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<clk_event_t>; // expected-note{{in instantiation of variable template specialization 'global_variable' requested here}} +} Index: clang/test/SemaOpenCL/sampler_t.cl =================================================================== --- clang/test/SemaOpenCL/sampler_t.cl +++ 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; Index: clang/test/SemaOpenCL/event_t.cl =================================================================== --- clang/test/SemaOpenCL/event_t.cl +++ 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'}} Index: clang/test/SemaOpenCL/clk_event_t.cl =================================================================== --- clang/test/SemaOpenCL/clk_event_t.cl +++ 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; } Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -6724,17 +6724,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; } @@ -6743,12 +6746,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; } } @@ -6761,9 +6764,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(); @@ -6775,8 +6778,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; } } @@ -6786,34 +6789,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: @@ -6822,12 +6811,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; } @@ -7254,10 +7244,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 @@ -7921,6 +7918,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<BlocksAttr>()) { Diag(NewVD->getLocation(), diag::err_opencl_block_storage_type); @@ -7942,6 +7942,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
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits