diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1773,6 +1773,31 @@ 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 +`_. + +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 ================= diff --git a/clang/include/clang/Basic/OpenCLExtensions.def b/clang/include/clang/Basic/OpenCLExtensions.def --- a/clang/include/clang/Basic/OpenCLExtensions.def +++ b/clang/include/clang/Basic/OpenCLExtensions.def @@ -70,6 +70,7 @@ // 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) diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -286,6 +286,7 @@ 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()); diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -129,6 +129,7 @@ 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"); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5019,6 +5019,7 @@ // (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)) || diff --git a/clang/test/Misc/amdgcn.languageOptsOpenCL.cl b/clang/test/Misc/amdgcn.languageOptsOpenCL.cl --- a/clang/test/Misc/amdgcn.languageOptsOpenCL.cl +++ b/clang/test/Misc/amdgcn.languageOptsOpenCL.cl @@ -19,6 +19,11 @@ #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 diff --git a/clang/test/Misc/nvptx.languageOptsOpenCL.cl b/clang/test/Misc/nvptx.languageOptsOpenCL.cl --- a/clang/test/Misc/nvptx.languageOptsOpenCL.cl +++ b/clang/test/Misc/nvptx.languageOptsOpenCL.cl @@ -27,6 +27,11 @@ #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 diff --git a/clang/test/Misc/r600.languageOptsOpenCL.cl b/clang/test/Misc/r600.languageOptsOpenCL.cl --- a/clang/test/Misc/r600.languageOptsOpenCL.cl +++ b/clang/test/Misc/r600.languageOptsOpenCL.cl @@ -35,6 +35,11 @@ #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 diff --git a/clang/test/SemaOpenCL/extension-version.cl b/clang/test/SemaOpenCL/extension-version.cl --- a/clang/test/SemaOpenCL/extension-version.cl +++ b/clang/test/SemaOpenCL/extension-version.cl @@ -24,6 +24,11 @@ #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 diff --git a/clang/test/SemaOpenCL/func.cl b/clang/test/SemaOpenCL/func.cl --- a/clang/test/SemaOpenCL/func.cl +++ b/clang/test/SemaOpenCL/func.cl @@ -1,18 +1,31 @@ // 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