From 8a3536251e74c97536dc0d2d30d103b187b90f6d Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Wed, 6 Jan 2021 14:55:09 -0800 Subject: [PATCH 1/8] Warn about forgetting to invoke void function If the user forgets the final `()` to invoke the function, they will now receive a warning. This is only relevant for void-returning functions where the result is not otherwise stored. For functions which return a value, this is both impossible to check and unnecessary, because they will probably receive other compile errors down the line. --- .clang-format | 1 + cmake/TestCompileError.cmake | 28 ++++---- cmake/test-compile-error.py | 72 +++++++++++++++++++ include/nickel/nickel.hpp | 31 +++++--- tests/CMakeLists.txt | 23 ++++-- .../compile_error/missing_eval_void.test.cpp | 21 ++++++ 6 files changed, 147 insertions(+), 29 deletions(-) create mode 100644 cmake/test-compile-error.py create mode 100644 tests/compile_error/missing_eval_void.test.cpp diff --git a/.clang-format b/.clang-format index b7cc01f..571ec31 100644 --- a/.clang-format +++ b/.clang-format @@ -19,6 +19,7 @@ BraceWrapping: SplitEmptyNamespace: true ColumnLimit: 100 IndentWidth: 4 +IndentPPDirectives: AfterHash Cpp11BracedListStyle: true NamespaceIndentation: All Standard: Cpp11 diff --git a/cmake/TestCompileError.cmake b/cmake/TestCompileError.cmake index 36f9ae3..2d7fbf0 100644 --- a/cmake/TestCompileError.cmake +++ b/cmake/TestCompileError.cmake @@ -1,10 +1,14 @@ +find_package(Python3 COMPONENTS Interpreter REQUIRED) + +set(__TEST_COMPILE_ERROR_PYTHON_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/test-compile-error.py) + function(add_compile_failure_test file) get_filename_component(abspath ${file} ABSOLUTE) file(RELATIVE_PATH target_name ${CMAKE_SOURCE_DIR} ${abspath}) string(MAKE_C_IDENTIFIER ${target_name} target_name) set(target_name compilefailure.test.${target_name}) - cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "LINK_LIBRARIES") + cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "LINK_LIBRARIES;COMPILE_OPTIONS") if(ARG_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unknown arguments ${ARG_UNPARSED_ARGUMENTS}") @@ -12,6 +16,7 @@ function(add_compile_failure_test file) add_library(${target_name} OBJECT ${file}) target_link_libraries(${target_name} PRIVATE ${ARG_LINK_LIBRARIES}) + target_compile_options(${target_name} PRIVATE ${ARG_COMPILE_OPTIONS}) set_property(TARGET ${target_name} PROPERTY EXCLUDE_FROM_ALL TRUE) set_property(TARGET ${target_name} PROPERTY EXCLUDE_FROM_DEFAULT_BUILD TRUE) set_property(SOURCE ${file} PROPERTY COMPILE_FAILURE_TEST_TARGET ${target_name}) @@ -23,20 +28,11 @@ function(add_compile_failure_test file) ) add_test( NAME test.${target_name} - COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --config $ --target testrunner.${target_name} - ) - set_tests_properties(test.${target_name} - PROPERTIES - WILL_FAIL TRUE + COMMAND Python3::Interpreter ${__TEST_COMPILE_ERROR_PYTHON_SCRIPT} + --cmake ${CMAKE_COMMAND} + --config $ + --binary_dir ${CMAKE_BINARY_DIR} + --target testrunner.${target_name} + --file ${abspath} ) endfunction() - -function(add_compile_failure_tests) - list(FIND ARGV LINK_LIBRARIES link_libraries_index) - list(SUBLIST ARGV 0 ${link_libraries_index} files) - list(SUBLIST ARGV ${link_libraries_index} -1 link_libraries) - - foreach(file IN LISTS files) - add_compile_failure_test(${file} ${link_libraries}) - endforeach() -endfunction() diff --git a/cmake/test-compile-error.py b/cmake/test-compile-error.py new file mode 100644 index 0000000..95f735e --- /dev/null +++ b/cmake/test-compile-error.py @@ -0,0 +1,72 @@ +import argparse +import subprocess +import sys +import re + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='Builds a CMake target that might fail') + parser.add_argument('--cmake', required=True, help='The ${CMAKE_COMMAND}') + parser.add_argument('--config', required=True, + help='The build configuration') + parser.add_argument('--binary_dir', required=True, + help='The ${CMAKE_BINARY_DIR}') + parser.add_argument('--target', required=True, + help='The CMake target to build') + parser.add_argument('--file', required=True, help='The source file') + + args = parser.parse_args() + + cmd = [args.cmake, '--build', args.binary_dir, + '--config', args.config, '--target', args.target] + print(' '.join(f"'{part}'" for part in cmd), flush=True) + result = subprocess.run(cmd, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, encoding='utf-8') + result.stderr = result.stdout + + with open(args.file, 'r') as f: + contents = f.read() + + error_matches = re.finditer( + r'// ERROR_MATCHES: (.*)$', contents, re.MULTILINE) + error_not_matches = re.finditer( + r'// ERROR_NOT_MATCHES: (.*)$', contents, re.MULTILINE) + + for re_match in error_matches: + regex = re_match.group(1) + try: + m = re.search(regex, result.stderr) + except: + print( + f'Regular Expression: {repr(regex)}', file=sys.stderr) + raise + if not m: + print( + f'Output did not match when it should have.\n' + + f'Regular Expression: {regex}\n' + + 'Stderr:\n' + + result.stderr, file=sys.stderr) + exit(1) + + for re_match in error_not_matches: + regex = re_match.group(1) + try: + m = re.search(regex, result.stderr) + except: + print( + f'Regular Expression: {repr(regex)}', file=sys.stderr) + raise + if m: + print( + f'Output matched when it should NOT have.\n' + + f'Regular Expression: {regex}\n' + + f'Match: {m.group()}\n' + + 'Stderr:\n' + + result.stderr, file=sys.stderr) + exit(1) + + if not error_matches and not error_not_matches: + if result.returncode == 0: + print(f'Expected compile failure, but compile succeeded.', file=sys.stderr) + exit(1) diff --git a/include/nickel/nickel.hpp b/include/nickel/nickel.hpp index 4623140..60a9359 100644 --- a/include/nickel/nickel.hpp +++ b/include/nickel/nickel.hpp @@ -15,6 +15,18 @@ #include #include +#ifdef __has_cpp_attribute +# if __has_cpp_attribute(nodiscard) >= 201907 +# define NICKEL_NODISCARD(...) [[nodiscard(__VA_ARGS__)]] +# elif __has_cpp_attribute(nodiscard) +# define NICKEL_NODISCARD(...) [[nodiscard]] +# else +# define NICKEL_NODISCARD(...) +# endif +#else +# define NICKEL_NODISCARD(...) +#endif + // std::forward #define NICKEL_DETAIL_FWD(...) static_cast(__VA_ARGS__) // std::move @@ -27,13 +39,13 @@ // Wraps std::trait_v<...> to work pre-C++17. #ifdef __cpp_lib_type_trait_variable_templates -#define NICKEL_IS_VOID(...) std::is_void_v<__VA_ARGS__> -#define NICKEL_IS_SAME(...) std::is_same_v<__VA_ARGS__> -#define NICKEL_IS_RVALUE_REFERENCE(...) std::is_rvalue_reference_v<__VA_ARGS__> +# define NICKEL_IS_VOID(...) std::is_void_v<__VA_ARGS__> +# define NICKEL_IS_SAME(...) std::is_same_v<__VA_ARGS__> +# define NICKEL_IS_RVALUE_REFERENCE(...) std::is_rvalue_reference_v<__VA_ARGS__> #else -#define NICKEL_IS_VOID(...) std::is_void<__VA_ARGS__>::value -#define NICKEL_IS_SAME(...) std::is_same<__VA_ARGS__>::value -#define NICKEL_IS_RVALUE_REFERENCE(...) std::is_rvalue_reference<__VA_ARGS__>::value +# define NICKEL_IS_VOID(...) std::is_void<__VA_ARGS__>::value +# define NICKEL_IS_SAME(...) std::is_same<__VA_ARGS__>::value +# define NICKEL_IS_RVALUE_REFERENCE(...) std::is_rvalue_reference<__VA_ARGS__>::value #endif namespace nickel { @@ -430,9 +442,10 @@ namespace nickel { typename Kwargs, // Any Kwargs typename Names, // The explicit named parameters typename CallEvalPolicy> // How to implement calling `Fn`. - class wrapped_fn : public wrapped_fn_base< - wrapped_fn, - Storage, Kwargs, Names> + class NICKEL_NODISCARD("Should be invoked with a bare () at the end") wrapped_fn + : public wrapped_fn_base< + wrapped_fn, Storage, Kwargs, + Names> { private: Defaults defaults_; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c65c054..ad5537c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,9 +53,24 @@ catch_discover_tests(test.nickel # Test that compilation fails include(TestCompileError) -file(GLOB_RECURSE compile_failure_test_sources CONFIGURE_DEPENDS "compile_error/*.test.cpp") +include(CheckCXXSourceCompiles) -add_compile_failure_tests( - ${compile_failure_test_sources} - LINK_LIBRARIES nickel::nickel +check_cxx_source_compiles([==[ + struct [[nodiscard /* "With a Reason */]] SomeType {}; + + SomeType someFunction() { return {}; } + + int main() { + auto x = someFunction(); + } + ]==] + NODISCARD_SUPPORTED + FAIL_REGEX "With a Reason" ) + +link_libraries(nickel::nickel) +add_compile_failure_test(compile_error/steal.nonrvalue.test.cpp) + +if(NODISCARD_SUPPORTED) + add_compile_failure_test(compile_error/missing_eval_void.test.cpp) +endif() diff --git a/tests/compile_error/missing_eval_void.test.cpp b/tests/compile_error/missing_eval_void.test.cpp new file mode 100644 index 0000000..5b3a4e9 --- /dev/null +++ b/tests/compile_error/missing_eval_void.test.cpp @@ -0,0 +1,21 @@ +// Copyright Justin Bassett 2019 - 2021. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#include + +// ERROR_MATCHES: do_something +// ERROR_MATCHES: bare \(\) + +NICKEL_NAME(abc); + +auto do_something() +{ + return nickel::wrap(abc)([](int abc) { (void)abc; }); +} + +void test() +{ + do_something().abc(2); +} From e312ab3dc3d46e79816b2efdf6be007f63170299 Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Wed, 6 Jan 2021 15:08:11 -0800 Subject: [PATCH 2/8] Massage test output requirements --- cmake/test-compile-error.py | 4 ++++ tests/compile_error/missing_eval_void.test.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/test-compile-error.py b/cmake/test-compile-error.py index 95f735e..71e81b1 100644 --- a/cmake/test-compile-error.py +++ b/cmake/test-compile-error.py @@ -70,3 +70,7 @@ if result.returncode == 0: print(f'Expected compile failure, but compile succeeded.', file=sys.stderr) exit(1) + + print('Test Passed.\n' + + 'Stderr\n' + + result.stderr) diff --git a/tests/compile_error/missing_eval_void.test.cpp b/tests/compile_error/missing_eval_void.test.cpp index 5b3a4e9..f8cf032 100644 --- a/tests/compile_error/missing_eval_void.test.cpp +++ b/tests/compile_error/missing_eval_void.test.cpp @@ -5,7 +5,7 @@ #include -// ERROR_MATCHES: do_something +// ERROR_MATCHES: missing_eval_void.test.cpp\D*20\b // ERROR_MATCHES: bare \(\) NICKEL_NAME(abc); From 2e79510e8a10b11cf8ed8c2f664f348b6927f4b2 Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Wed, 6 Jan 2021 15:25:31 -0800 Subject: [PATCH 3/8] Fix the checking if NODISCARD is supported --- tests/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ad5537c..f1b41af 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,7 +56,7 @@ include(TestCompileError) include(CheckCXXSourceCompiles) check_cxx_source_compiles([==[ - struct [[nodiscard /* "With a Reason */]] SomeType {}; + struct [[nodiscard]] SomeType {}; SomeType someFunction() { return {}; } @@ -65,7 +65,6 @@ check_cxx_source_compiles([==[ } ]==] NODISCARD_SUPPORTED - FAIL_REGEX "With a Reason" ) link_libraries(nickel::nickel) From d86cd26e6bc67a6e1342ee9b2a51b06f69761ec9 Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Wed, 6 Jan 2021 15:28:05 -0800 Subject: [PATCH 4/8] Don't require that the nodiscard message is visible at all --- tests/compile_error/missing_eval_void.test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/compile_error/missing_eval_void.test.cpp b/tests/compile_error/missing_eval_void.test.cpp index f8cf032..c14158e 100644 --- a/tests/compile_error/missing_eval_void.test.cpp +++ b/tests/compile_error/missing_eval_void.test.cpp @@ -6,7 +6,6 @@ #include // ERROR_MATCHES: missing_eval_void.test.cpp\D*20\b -// ERROR_MATCHES: bare \(\) NICKEL_NAME(abc); From e24f684c31a1435dfce15bc1ecc1e5ee75e699fa Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Wed, 6 Jan 2021 15:33:29 -0800 Subject: [PATCH 5/8] Fix line number --- tests/compile_error/missing_eval_void.test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compile_error/missing_eval_void.test.cpp b/tests/compile_error/missing_eval_void.test.cpp index c14158e..fde0227 100644 --- a/tests/compile_error/missing_eval_void.test.cpp +++ b/tests/compile_error/missing_eval_void.test.cpp @@ -5,7 +5,7 @@ #include -// ERROR_MATCHES: missing_eval_void.test.cpp\D*20\b +// ERROR_MATCHES: missing_eval_void.test.cpp\D*19\b NICKEL_NAME(abc); From 12d54942ec2e61d5d9667f8b69e3e3f3f71af404 Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Wed, 6 Jan 2021 16:19:04 -0800 Subject: [PATCH 6/8] Silence irrelevant Clang warnings about C++Future Even though we used feature-test macros, Clang emitted warnings about using features from C++Future. This change silences those warnings by using _Pragma to ignonre the particular warning flag for only the offending constructs. This requires quite a bit of compiler detection preprocessor code, but short of Clang getting its act together with these warnings around feature-test macros, there's not much else we can realistically do. --- include/nickel/nickel.hpp | 58 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/include/nickel/nickel.hpp b/include/nickel/nickel.hpp index 60a9359..02a7541 100644 --- a/include/nickel/nickel.hpp +++ b/include/nickel/nickel.hpp @@ -15,18 +15,62 @@ #include #include +#if defined(__clang__) +# define NICKEL_DETAIL_IS_CLANG +#elif defined(__GNUC__) +# define NICKEL_DETAIL_IS_GCC +#elif defined(_MSC_VER) +# define NICKEL_DETAIL_IS_MSVC +#endif + +#ifdef NICKEL_DETAIL_IS_CLANG +# define NICKEL_DETAIL_CLANG_PRAGMA(...) _Pragma(__VA_ARGS__) +# define NICKEL_DETAIL_CLANG_WIGNORE(warning, ...) \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignore " #warning) \ + __VA_ARGS__ _Pragma("clang diagnostic pop") +#else +# define NICKEL_DETAIL_CLANG_PRAGMA(...) +# define NICKEL_DETAIL_CLANG_WIGNORE(warning, ...) __VA_ARGS__ +#endif + +#ifdef NICKEL_DETAIL_IS_GCC +# define NICKEL_DETAIL_GCC_PRAGMA(...) _Pragma(__VA_ARGS__) +# define NICKEL_DETAIL_GCC_WIGNORE(warning, ...) \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignore " #warning) \ + __VA_ARGS__ _Pragma("GCC diagnostic pop") +#else +# define NICKEL_DETAIL_GCC_PRAGMA(...) +# define NICKEL_DETAIL_GCC_WIGNORE(warning, ...) __VA_ARGS__ +#endif + +#ifdef NICKEL_DETAIL_IS_MSVC +# define NICKEL_DETAIL_MSVC_PRAGMA(...) _Pragma(__VA_ARGS__) +#else +# define NICKEL_DETAIL_MSVC_PRAGMA(...) +#endif + +#define NICKEL_CLANG_PRAGMA NICKEL_DETAIL_CLANG_PRAGMA +#define NICKEL_CLANG_WIGNORE NICKEL_DETAIL_CLANG_WIGNORE +#define NICKEL_GCC_PRAGMA NICKEL_DETAIL_GCC_PRAGMA +#define NICKEL_GCC_WIGNORE NICKEL_DETAIL_GCC_WIGNORE +#define NICKEL_MSVC_PRAGMA NICKEL_DETAIL_MSVC_PRAGMA + #ifdef __has_cpp_attribute # if __has_cpp_attribute(nodiscard) >= 201907 -# define NICKEL_NODISCARD(...) [[nodiscard(__VA_ARGS__)]] +# define NICKEL_DETAIL_NODISCARD(...) \ + NICKEL_CLANG_WIGNORE("-Wc++20-extensions", [[nodiscard(__VA_ARGS__)]]) # elif __has_cpp_attribute(nodiscard) -# define NICKEL_NODISCARD(...) [[nodiscard]] +# define NICKEL_DETAIL_NODISCARD(...) \ + NICKEL_CLANG_WIGNORE("-Wc++17-extensions", [[nodiscard]]) # else -# define NICKEL_NODISCARD(...) +# define NICKEL_DETAIL_NODISCARD(...) # endif #else -# define NICKEL_NODISCARD(...) +# define NICKEL_DETAIL_NODISCARD(...) #endif +#define NICKEL_NODISCARD NICKEL_DETAIL_NODISCARD + // std::forward #define NICKEL_DETAIL_FWD(...) static_cast(__VA_ARGS__) // std::move @@ -879,5 +923,11 @@ namespace nickel { #undef NICKEL_IS_VOID #undef NICKEL_IS_SAME #undef NICKEL_IS_RVALUE_REFERENCE +#undef NICKEL_NODISCARD +#undef NICKEL_MSVC_PRAGMA +#undef NICKEL_GCC_WIGNORE +#undef NICKEL_GCC_PRAGMA +#undef NICKEL_CLANG_WIGNORE +#undef NICKEL_CLANG_PRAGMA #endif From 07a2f476f0e67fbb2442806db1ae1940e5f89399 Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Wed, 6 Jan 2021 16:27:28 -0800 Subject: [PATCH 7/8] Fix pragma internal details --- include/nickel/nickel.hpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/include/nickel/nickel.hpp b/include/nickel/nickel.hpp index 02a7541..0f7071b 100644 --- a/include/nickel/nickel.hpp +++ b/include/nickel/nickel.hpp @@ -23,28 +23,31 @@ # define NICKEL_DETAIL_IS_MSVC #endif +#define NICKEL_DETAIL_STR2(...) #__VA_ARGS__ +#define NICKEL_DETAIL_STR(...) NICKEL_DETAIL_STR2(__VA_ARGS__) + #ifdef NICKEL_DETAIL_IS_CLANG -# define NICKEL_DETAIL_CLANG_PRAGMA(...) _Pragma(__VA_ARGS__) -# define NICKEL_DETAIL_CLANG_WIGNORE(warning, ...) \ - _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignore " #warning) \ - __VA_ARGS__ _Pragma("clang diagnostic pop") +# define NICKEL_DETAIL_CLANG_PRAGMA(...) _Pragma(NICKEL_DETAIL_STR(__VA_ARGS__)) #else # define NICKEL_DETAIL_CLANG_PRAGMA(...) -# define NICKEL_DETAIL_CLANG_WIGNORE(warning, ...) __VA_ARGS__ #endif +#define NICKEL_DETAIL_CLANG_WIGNORE(warning, ...) \ + NICKEL_DETAIL_CLANG_PRAGMA(clang diagnostic push) \ + NICKEL_DETAIL_CLANG_PRAGMA(clang diagnostic ignore warning) \ + __VA_ARGS__ NICKEL_DETAIL_CLANG_PRAGMA(clang diagnostic pop) #ifdef NICKEL_DETAIL_IS_GCC -# define NICKEL_DETAIL_GCC_PRAGMA(...) _Pragma(__VA_ARGS__) -# define NICKEL_DETAIL_GCC_WIGNORE(warning, ...) \ - _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignore " #warning) \ - __VA_ARGS__ _Pragma("GCC diagnostic pop") +# define NICKEL_DETAIL_GCC_PRAGMA(...) _Pragma(NICKEL_DETAIL_STR(__VA_ARGS__)) #else # define NICKEL_DETAIL_GCC_PRAGMA(...) -# define NICKEL_DETAIL_GCC_WIGNORE(warning, ...) __VA_ARGS__ #endif +#define NICKEL_DETAIL_GCC_WIGNORE(warning, ...) \ + NICKEL_DETAIL_GCC_PRAGMA(GCC diagnostic push) \ + NICKEL_DETAIL_GCC_PRAGMA(GCC diagnostic ignore warning) \ + __VA_ARGS__ NICKEL_DETAIL_GCC_PRAGMA(GCC diagnostic pop) #ifdef NICKEL_DETAIL_IS_MSVC -# define NICKEL_DETAIL_MSVC_PRAGMA(...) _Pragma(__VA_ARGS__) +# define NICKEL_DETAIL_MSVC_PRAGMA(...) _Pragma(NICKEL_DETAIL_STR(__VA_ARGS__)) #else # define NICKEL_DETAIL_MSVC_PRAGMA(...) #endif From 3772aa0e7af160ec4774eee6e64f13c91a77ab30 Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Wed, 6 Jan 2021 16:29:18 -0800 Subject: [PATCH 8/8] Fix warning ignoring pragma term --- include/nickel/nickel.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nickel/nickel.hpp b/include/nickel/nickel.hpp index 0f7071b..51d98ea 100644 --- a/include/nickel/nickel.hpp +++ b/include/nickel/nickel.hpp @@ -33,7 +33,7 @@ #endif #define NICKEL_DETAIL_CLANG_WIGNORE(warning, ...) \ NICKEL_DETAIL_CLANG_PRAGMA(clang diagnostic push) \ - NICKEL_DETAIL_CLANG_PRAGMA(clang diagnostic ignore warning) \ + NICKEL_DETAIL_CLANG_PRAGMA(clang diagnostic ignored warning) \ __VA_ARGS__ NICKEL_DETAIL_CLANG_PRAGMA(clang diagnostic pop) #ifdef NICKEL_DETAIL_IS_GCC @@ -43,7 +43,7 @@ #endif #define NICKEL_DETAIL_GCC_WIGNORE(warning, ...) \ NICKEL_DETAIL_GCC_PRAGMA(GCC diagnostic push) \ - NICKEL_DETAIL_GCC_PRAGMA(GCC diagnostic ignore warning) \ + NICKEL_DETAIL_GCC_PRAGMA(GCC diagnostic ignored warning) \ __VA_ARGS__ NICKEL_DETAIL_GCC_PRAGMA(GCC diagnostic pop) #ifdef NICKEL_DETAIL_IS_MSVC