void (*fp)(); // error - pointers to function are not allowed
}
+``__cl_clang_variadic_functions``
+---------------------------------
+
+With this extension it is possible to enable variadic arguments in functions
+using regular OpenCL extension pragma mechanism detailed in `the OpenCL
+Extension Specification, section 1.2
+<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
+
+This is not conformant behavior and it can only be used portably when the
+functions with variadic prototypes do not get generated in binary e.g. the
+variadic prototype is used to spesify a function type with any number of
+arguments in metaprogramming algorithms in C++ for OpenCL.
+
+This extensions can also be used when the kernel code is intended for targets
+supporting the variadic arguments e.g. majority of CPU targets.
+
+**Example of Use**:
+
+.. code-block:: c++
+
+ #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+ void foo(int a, ...); // compiled - no diagnostic generated
+
+ #pragma OPENCL EXTENSION __cl_clang_variadic_functions : disable
+ void bar(int a, ...); // error - variadic prototype is not allowed
Builtin Functions
=================
// Clang Extensions.
OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U)
OPENCLEXT_INTERNAL(__cl_clang_function_pointers, 100, ~0U)
+OPENCLEXT_INTERNAL(__cl_clang_variadic_functions, 100, ~0U)
// AMD OpenCL extensions
OPENCLEXT_INTERNAL(cl_amd_media_ops, 100, ~0U)
auto &Opts = getSupportedOpenCLOpts();
Opts.support("cl_clang_storage_class_specifiers");
Opts.support("__cl_clang_function_pointers");
+ Opts.support("__cl_clang_variadic_functions");
bool IsAMDGCN = isAMDGCN(getTriple());
auto &Opts = getSupportedOpenCLOpts();
Opts.support("cl_clang_storage_class_specifiers");
Opts.support("__cl_clang_function_pointers");
+ Opts.support("__cl_clang_variadic_functions");
Opts.support("cl_khr_fp64");
Opts.support("cl_khr_byte_addressable_store");
// (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
// We also allow here any toolchain reserved identifiers.
if (FTI.isVariadic &&
+ !S.getOpenCLOptions().isEnabled("__cl_clang_variadic_functions") &&
!(D.getIdentifier() &&
((D.getIdentifier()->getName() == "printf" &&
(LangOpts.OpenCLCPlusPlus || LangOpts.OpenCLVersion >= 120)) ||
#endif
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
+#ifndef __cl_clang_variadic_functions
+#error "Missing __cl_clang_variadic_functions define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+
#ifndef cl_khr_fp16
#error "Missing cl_khr_fp16 define"
#endif
#endif
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
+#ifndef __cl_clang_variadic_functions
+#error "Missing __cl_clang_variadic_functions define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+
#ifdef cl_khr_fp16
#error "Incorrect cl_khr_fp16 define"
#endif
#endif
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
+#ifndef __cl_clang_variadic_functions
+#error "Missing __cl_clang_variadic_functions define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+
#ifdef cl_khr_fp16
#error "Incorrect cl_khr_fp16 define"
#endif
#endif
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
+#ifndef __cl_clang_variadic_functions
+#error "Missing __cl_clang_variadic_functions define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+
#ifndef cl_khr_fp16
#error "Missing cl_khr_fp16 define"
#endif
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -triple spir-unknown-unknown
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -triple spir-unknown-unknown -DFUNCPTREXT
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -triple spir-unknown-unknown -DVARARG
#ifdef FUNCPTREXT
#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable
#endif
+#ifdef VARARGEXT
+#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+#endif
// Variadic functions
-void vararg_f(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
+void vararg_f(int, ...);
+#ifndef VARARGEXT
+// expected-error@-2 {{invalid prototype, variadic arguments are not allowed in OpenCL}}
+#endif
void __vararg_f(int, ...);
-typedef void (*vararg_fptr_t)(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
+typedef void (*vararg_fptr_t)(int, ...);
+#ifndef VARARGEXT
+// expected-error@-2 {{invalid prototype, variadic arguments are not allowed in OpenCL}}
+#endif
#ifndef FUNCPTREXT
-// expected-error@-2 {{pointers to functions are not allowed}}
+// expected-error@-5 {{pointers to functions are not allowed}}
+#endif
+int printf(__constant const char *st, ...);
+#ifndef VARARGEXT
+// expected-error@-2 {{invalid prototype, variadic arguments are not allowed in OpenCL}}
#endif
-int printf(__constant const char *st, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
// Struct type with function pointer field
typedef struct s