]> git.proxmox.com Git - ceph.git/blame - ceph/src/fmt/test/compile-error-test/CMakeLists.txt
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / fmt / test / compile-error-test / CMakeLists.txt
CommitLineData
11fdf7f2
TL
1# Test if compile errors are produced where necessary.
2
20effc67 3cmake_minimum_required(VERSION 3.1...3.18)
1e59de90 4project(compile-error-test CXX)
11fdf7f2 5
1e59de90
TL
6set(fmt_headers "
7 #include <fmt/format.h>
8 #include <fmt/xchar.h>
9 #include <fmt/ostream.h>
10 #include <iostream>
11")
11fdf7f2 12
1e59de90
TL
13set(error_test_names "")
14set(non_error_test_content "")
15
16# For error tests (we expect them to produce compilation error):
17# * adds a name of test into `error_test_names` list
18# * generates a single source file (with the same name) for each test
19# For non-error tests (we expect them to compile successfully):
20# * adds a code segment as separate function to `non_error_test_content`
21function (expect_compile name code_fragment)
22 cmake_parse_arguments(EXPECT_COMPILE "ERROR" "" "" ${ARGN})
23 string(MAKE_C_IDENTIFIER "${name}" test_name)
24
25 if (EXPECT_COMPILE_ERROR)
26 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/${test_name}.cc" "
27 ${fmt_headers}
28 void ${test_name}() {
29 ${code_fragment}
30 }
31 ")
32 set(error_test_names_copy "${error_test_names}")
33 list(APPEND error_test_names_copy "${test_name}")
34 set(error_test_names "${error_test_names_copy}" PARENT_SCOPE)
35 else()
36 set(non_error_test_content "
37 ${non_error_test_content}
38 void ${test_name}() {
39 ${code_fragment}
40 }" PARENT_SCOPE)
41 endif()
11fdf7f2
TL
42endfunction ()
43
1e59de90
TL
44# Generates a source file for non-error test with `non_error_test_content` and
45# CMake project file with all error and single non-error test targets.
46function (run_tests)
47 set(cmake_targets "")
48 foreach(test_name IN LISTS error_test_names)
49 set(cmake_targets "
50 ${cmake_targets}
51 add_library(test-${test_name} ${test_name}.cc)
52 target_link_libraries(test-${test_name} PRIVATE fmt::fmt)
53 ")
54 endforeach()
55
56 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/non_error_test.cc" "
57 ${fmt_headers}
58 ${non_error_test_content}
59 ")
60 set(cmake_targets "
61 ${cmake_targets}
62 add_library(non-error-test non_error_test.cc)
63 target_link_libraries(non-error-test PRIVATE fmt::fmt)
64 ")
65
66 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/CMakeLists.txt" "
67 cmake_minimum_required(VERSION 3.1...3.18)
68 project(tests CXX)
69 add_subdirectory(${FMT_DIR} fmt)
70 ${cmake_targets}
71 ")
72
73 set(build_directory "${CMAKE_CURRENT_BINARY_DIR}/test/build")
74 file(MAKE_DIRECTORY "${build_directory}")
75 execute_process(
76 COMMAND
77 "${CMAKE_COMMAND}"
78 "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
79 "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
80 "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
81 "-DCMAKE_GENERATOR=${CMAKE_GENERATOR}"
82 "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
83 "-DFMT_DIR=${FMT_DIR}"
84 "${CMAKE_CURRENT_BINARY_DIR}/test"
85 WORKING_DIRECTORY "${build_directory}"
86 RESULT_VARIABLE result_var
87 OUTPUT_VARIABLE output_var
88 ERROR_VARIABLE output_var)
89 if (NOT result_var EQUAL 0)
90 message(FATAL_ERROR "Unable to configure:\n${output_var}")
91 endif()
92
93 foreach(test_name IN LISTS error_test_names)
94 execute_process(
95 COMMAND
96 "${CMAKE_COMMAND}" --build "${build_directory}" --target "test-${test_name}"
97 WORKING_DIRECTORY "${build_directory}"
98 RESULT_VARIABLE result_var
99 OUTPUT_VARIABLE output_var
100 ERROR_QUIET)
101 if (result_var EQUAL 0)
102 message(SEND_ERROR "No compile error for \"${test_name}\":\n${output_var}")
103 endif ()
104 endforeach()
105
106 execute_process(
107 COMMAND
108 "${CMAKE_COMMAND}" --build "${build_directory}" --target "non-error-test"
109 WORKING_DIRECTORY "${build_directory}"
110 RESULT_VARIABLE result_var
111 OUTPUT_VARIABLE output_var
112 ERROR_VARIABLE output_var)
113 if (NOT result_var EQUAL 0)
114 message(SEND_ERROR "Compile error for combined non-error test:\n${output_var}")
11fdf7f2
TL
115 endif ()
116endfunction ()
117
1e59de90 118
11fdf7f2 119# check if the source file skeleton compiles
1e59de90
TL
120expect_compile(check "")
121expect_compile(check-error "compilation_error" ERROR)
11fdf7f2
TL
122
123# Formatting a wide character with a narrow format string is forbidden.
1e59de90
TL
124expect_compile(wide-character-narrow-format-string "fmt::format(L\"{}\", L'a');")
125expect_compile(wide-character-narrow-format-string-error "fmt::format(\"{}\", L'a');" ERROR)
11fdf7f2
TL
126
127# Formatting a wide string with a narrow format string is forbidden.
1e59de90
TL
128expect_compile(wide-string-narrow-format-string "fmt::format(L\"{}\", L\"foo\");")
129expect_compile(wide-string-narrow-format-string-error "fmt::format(\"{}\", L\"foo\");" ERROR)
11fdf7f2
TL
130
131# Formatting a narrow string with a wide format string is forbidden because
132# mixing UTF-8 with UTF-16/32 can result in an invalid output.
1e59de90
TL
133expect_compile(narrow-string-wide-format-string "fmt::format(L\"{}\", L\"foo\");")
134expect_compile(narrow-string-wide-format-string-error "fmt::format(L\"{}\", \"foo\");" ERROR)
11fdf7f2 135
1e59de90
TL
136expect_compile(cast-to-string "
137 struct S {
138 operator std::string() const { return std::string(); }
139 };
140 fmt::format(\"{}\", std::string(S()));
141")
142expect_compile(cast-to-string-error "
11fdf7f2
TL
143 struct S {
144 operator std::string() const { return std::string(); }
145 };
146 fmt::format(\"{}\", S());
1e59de90
TL
147" ERROR)
148
149# Formatting a function
150expect_compile(format-function "
151 void (*f)();
152 fmt::format(\"{}\", fmt::ptr(f));
11fdf7f2 153")
1e59de90
TL
154expect_compile(format-function-error "
155 void (*f)();
156 fmt::format(\"{}\", f);
157" ERROR)
158
159# Formatting an unformattable argument should always be a compile time error
160expect_compile(format-lots-of-arguments-with-unformattable "
161 struct E {};
162 fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, E());
163" ERROR)
164expect_compile(format-lots-of-arguments-with-function "
165 void (*f)();
166 fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, f);
167" ERROR)
168
169# Check if user-defined literals are available
170include(CheckCXXSourceCompiles)
171set(CMAKE_REQUIRED_FLAGS ${CXX_STANDARD_FLAG})
172check_cxx_source_compiles("
173 void operator\"\" _udl(long double);
174 int main() {}"
175 SUPPORTS_USER_DEFINED_LITERALS)
176set(CMAKE_REQUIRED_FLAGS )
177if (NOT SUPPORTS_USER_DEFINED_LITERALS)
178 set (SUPPORTS_USER_DEFINED_LITERALS OFF)
179endif ()
11fdf7f2
TL
180
181# Make sure that compiler features detected in the header
182# match the features detected in CMake.
183if (SUPPORTS_USER_DEFINED_LITERALS)
184 set(supports_udl 1)
185else ()
186 set(supports_udl 0)
187endif ()
1e59de90
TL
188expect_compile(udl-check "
189 #if FMT_USE_USER_DEFINED_LITERALS != ${supports_udl}
190 # error
191 #endif
192")
193
194if (CMAKE_CXX_STANDARD GREATER_EQUAL 20)
195 # Compile-time argument type check
196 expect_compile(format-string-number-spec "
197 #ifdef FMT_HAS_CONSTEVAL
198 fmt::format(\"{:d}\", 42);
199 #endif
200 ")
201 expect_compile(format-string-number-spec-error "
202 #ifdef FMT_HAS_CONSTEVAL
203 fmt::format(\"{:d}\", \"I am not a number\");
204 #else
205 #error
206 #endif
207 " ERROR)
208 expect_compile(print-string-number-spec-error "
209 #ifdef FMT_HAS_CONSTEVAL
210 fmt::print(\"{:d}\", \"I am not a number\");
211 #else
212 #error
213 #endif
214 " ERROR)
215 expect_compile(print-stream-string-number-spec-error "
216 #ifdef FMT_HAS_CONSTEVAL
217 fmt::print(std::cout, \"{:d}\", \"I am not a number\");
218 #else
219 #error
220 #endif
221 " ERROR)
222
223 # Compile-time argument name check
224 expect_compile(format-string-name "
225 #if defined(FMT_HAS_CONSTEVAL) && FMT_USE_NONTYPE_TEMPLATE_ARGS
226 using namespace fmt::literals;
227 fmt::print(\"{foo}\", \"foo\"_a=42);
228 #endif
229 ")
230 expect_compile(format-string-name-error "
231 #if defined(FMT_HAS_CONSTEVAL) && FMT_USE_NONTYPE_TEMPLATE_ARGS
232 using namespace fmt::literals;
233 fmt::print(\"{foo}\", \"bar\"_a=42);
234 #else
235 #error
236 #endif
237 " ERROR)
238endif ()
239
240# Run all tests
241run_tests()