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

Reply via email to