https://github.com/Men-cotton created https://github.com/llvm/llvm-project/pull/234347
Validation is limited to function parameters and misses invalid pipe typedefs such as `typedef pipe void P;`. Move this validation into `BuildReadPipeType` and `BuildWritePipeType` so declarations and template instantiations follow the same packet-type restrictions. Reject pointer, reference, block pointer, non-object, and non-dependent incomplete packet types. Defer checks that require a concrete type until template substitution, but diagnose dependent function types immediately. Report errors at the `pipe` keyword. Assisted-by: Codex / GPT-5.6 Sol + GPT-6 Astra >From c3ca3b719f0e5b02acf9225628714ac6c81da378 Mon Sep 17 00:00:00 2001 From: mencotton <[email protected]> Date: Tue, 1 Sep 2026 22:26:59 +0900 Subject: [PATCH] [OpenCL] Diagnose invalid pipe packet types when formed Validation limited to function parameters misses invalid pipe typedefs such as `typedef pipe void P;`. Move this validation into `BuildReadPipeType` and `BuildWritePipeType` so declarations and template instantiations follow the same packet-type restrictions. Reject pointer, reference, block pointer, non-object, and non-dependent incomplete packet types. Defer checks that require a concrete type until template substitution, but diagnose dependent function types immediately. Report errors at the `pipe` keyword. Assisted-by: Codex / GPT-5.6 Sol + GPT-6 Astra --- .../clang/Basic/DiagnosticSemaKinds.td | 5 +- clang/lib/Parse/ParseDecl.cpp | 6 +-- clang/lib/Sema/DeclSpec.cpp | 1 + clang/lib/Sema/SemaDecl.cpp | 11 ----- clang/lib/Sema/SemaType.cpp | 29 +++++++++++- clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl | 46 +++++++++++++++---- 6 files changed, 72 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a23667f1fb1c2c..bd8ceb1031d659 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11920,8 +11920,9 @@ def err_opencl_global_invalid_addr_space : Error< "%select{program scope|static local|extern}0 variable must reside in %1 address space">; def err_missing_actual_pipe_type : Error< "missing actual type specifier for pipe">; -def err_reference_pipe_type : Error < - "pipes packet types cannot be of reference type">; +def err_invalid_pipe_packet_type : Error< + "%select{pointer|reference|block pointer|non-object|incomplete}0 type %1 " + "cannot be used as a pipe packet type">; def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">; def err_opencl_kernel_attr : Error<"attribute %0 can only be applied to an OpenCL kernel function">; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index ada54c85695c34..e452c312702491 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6654,9 +6654,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, DeclSpec DS(AttrFactory); ParseTypeQualifierListOpt(DS); - D.AddTypeInfo( - DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()), - std::move(DS.getAttributes()), SourceLocation()); + D.AddTypeInfo(DeclaratorChunk::getPipe(DS.getTypeQualifiers(), + D.getDeclSpec().getPipeLoc()), + std::move(DS.getAttributes()), SourceLocation()); } // Not a pointer, C++ reference, or block. diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index e83ba3db9f1fd6..dfa7a79d1f92b2 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -905,6 +905,7 @@ bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc, if (isPipe) { TypeSpecPipe = static_cast<unsigned>(TypeSpecifiersPipe::Pipe); + TQ_pipeLoc = Loc; } return false; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 21e279ec2000c3..854ed123bb558c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11433,17 +11433,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, for (const ParmVarDecl *Param : NewFD->parameters()) { QualType PT = Param->getType(); - // OpenCL 2.0 pipe restrictions forbids pipe packet types to be non-value - // types. - if (getLangOpts().getOpenCLCompatibleVersion() >= 200) { - if(const PipeType *PipeTy = PT->getAs<PipeType>()) { - QualType ElemTy = PipeTy->getElementType(); - if (ElemTy->isPointerOrReferenceType()) { - Diag(Param->getTypeSpecStartLoc(), diag::err_reference_pipe_type); - D.setInvalidType(); - } - } - } // WebAssembly tables can't be used as function parameters. if (Context.getTargetInfo().getTriple().isWasm()) { if (PT->getUnqualifiedDesugaredType()->isWebAssemblyTableType()) { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index af0403e73480c0..578c73f2a00d15 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1970,11 +1970,35 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, return Context.getRValueReferenceType(T); } +static bool checkOpenCLPipePacketType(Sema &S, QualType T, SourceLocation Loc) { + if (T->isPointerType()) + return S.Diag(Loc, diag::err_invalid_pipe_packet_type) + << /*pointer*/ 0 << T; + if (T->isReferenceType()) + return S.Diag(Loc, diag::err_invalid_pipe_packet_type) + << /*reference*/ 1 << T; + if (T->isBlockPointerType()) + return S.Diag(Loc, diag::err_invalid_pipe_packet_type) + << /*block pointer*/ 2 << T; + if (!T->isObjectType()) + return S.Diag(Loc, diag::err_invalid_pipe_packet_type) + << /*non-object*/ 3 << T; + if (!T->isDependentType() && !S.isCompleteType(Loc, T)) + return S.Diag(Loc, diag::err_invalid_pipe_packet_type) + << /*incomplete*/ 4 << T; + + return false; +} + QualType Sema::BuildReadPipeType(QualType T, SourceLocation Loc) { + if (checkOpenCLPipePacketType(*this, T, Loc)) + return QualType(); return Context.getReadPipeType(T); } QualType Sema::BuildWritePipeType(QualType T, SourceLocation Loc) { + if (checkOpenCLPipePacketType(*this, T, Loc)) + return QualType(); return Context.getWritePipeType(T); } @@ -5498,8 +5522,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case DeclaratorChunk::Pipe: { T = S.BuildReadPipeType(T, DeclType.Loc); - processTypeAttrs(state, T, TAL_DeclSpec, - D.getMutableDeclSpec().getAttributes()); + if (!T.isNull()) + processTypeAttrs(state, T, TAL_DeclSpec, + D.getMutableDeclSpec().getAttributes()); break; } } diff --git a/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl b/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl index 089b2f16765fd0..a570bd3ff75ca4 100644 --- a/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl +++ b/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -Wno-strict-prototypes -cl-std=CL2.0 +// RUN: %clang_cc1 %s -verify=expected,blocks -pedantic -fsyntax-only -Wno-strict-prototypes -cl-std=CL2.0 -fblocks -DTEST_BLOCK_POINTER_PACKET // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -Wno-strict-prototypes -cl-std=CL3.0 -cl-ext=+__opencl_c_pipes,+__opencl_c_generic_address_space,+__opencl_c_program_scope_global_variables // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -Wno-strict-prototypes -cl-std=CL3.0 -cl-ext=+__opencl_c_pipes,+__opencl_c_generic_address_space,-__opencl_c_program_scope_global_variables,-__opencl_c_device_enqueue // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++1.0 @@ -8,21 +9,50 @@ 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}} -extern pipe write_only int get_pipe(void); // expected-error {{'write_only' attribute only applies to parameters and typedefs}} -#if (__OPENCL_CPP_VERSION__ == 100) || (__OPENCL_C_VERSION__ == 200) || ((__OPENCL_CPP_VERSION__ == 202100 || __OPENCL_C_VERSION__ == 300) && defined(__opencl_c_program_scope_global_variables)) -// expected-error-re@-2{{type '__global write_only pipe int ({{(void)?}})' can only be used as a function parameter in OpenCL}} -#else -// FIXME: '__private' here makes no sense since program scope variables feature is not supported, should diagnose as '__global' probably -// expected-error-re@-5{{type '__private write_only pipe int ({{(void)?}})' can only be used as a function parameter in OpenCL}} -#endif +extern pipe write_only int get_pipe(void); // expected-error {{'write_only' attribute only applies to parameters and typedefs}} expected-error-re {{non-object type 'int ({{(void)?}})' cannot be used as a pipe packet type}} global pipe notype1, notype2; // expected-error {{missing actual type specifier for pipe}} kernel void test_invalid_reserved_id(reserve_id_t ID) { // expected-error {{'__private reserve_id_t' cannot be used as the type of a kernel parameter}} } -void test1(pipe int *p) {// expected-error {{pipes packet types cannot be of reference type}} +void test1(pipe int *p) {// expected-error {{pointer type '__generic int *' cannot be used as a pipe packet type}} } + +#ifdef __OPENCL_CPP_VERSION__ +void reference_packet_type(pipe int &p) {} // expected-error {{reference type '__generic int &' cannot be used as a pipe packet type}} +#endif + +#ifdef TEST_BLOCK_POINTER_PACKET +typedef void (^block_t)(void); +void block_pointer_packet_type(pipe block_t p) {} // blocks-error-re {{block pointer type 'block_t'{{.*}} cannot be used as a pipe packet type}} +#endif + +typedef pipe void invalid_pipe_typedef; // expected-error {{non-object type 'void' cannot be used as a pipe packet type}} + +typedef void function_type(void); +void non_object_packet_types( + pipe void p1, // expected-error {{non-object type 'void' cannot be used as a pipe packet type}} + pipe function_type p2) {} // expected-error-re {{non-object type 'function_type' (aka 'void ({{(void)?}})') cannot be used as a pipe packet type}} + +struct incomplete; +typedef pipe struct incomplete invalid_incomplete_pipe; // expected-error {{incomplete type 'struct incomplete' cannot be used as a pipe packet type}} + +#ifdef __OPENCL_CPP_VERSION__ +template <typename T> +void non_object_packet_in_template(pipe void p) {} // expected-error {{non-object type 'void' cannot be used as a pipe packet type}} + +template <typename T> +void dependent_packet_type(pipe T p) {} + +template <typename T> using dependent_function_type = T(); +template <typename T> +void dependent_function_packet_type(pipe dependent_function_type<T> p) {} // expected-error {{non-object type 'dependent_function_type<T>' (aka 'T ()') cannot be used as a pipe packet type}} + +template <typename T> struct packet_type { T value; }; +void class_template_packet_type(pipe packet_type<int> p) {} +#endif + void test2(pipe p) {// expected-error {{missing actual type specifier for pipe}} } void test3(int pipe p) {// expected-error {{cannot combine with previous 'int' declaration specifier}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
