| 1 | /* |
| 2 | Copyright (c) 2005-2019 Intel Corporation |
| 3 | |
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | you may not use this file except in compliance with the License. |
| 6 | You may obtain a copy of the License at |
| 7 | |
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | /** |
| 18 | This test ensures that tbb.h brings in all the public TBB interface definitions, |
| 19 | and if all the necessary symbols are exported from the library. |
| 20 | |
| 21 | Most of the checks happen at the compilation or link phases. |
| 22 | **/ |
| 23 | #if __TBB_CPF_BUILD |
| 24 | // Add testing of preview features |
| 25 | #define TBB_PREVIEW_AGGREGATOR 1 |
| 26 | #define TBB_PREVIEW_CONCURRENT_LRU_CACHE 1 |
| 27 | #define TBB_PREVIEW_VARIADIC_PARALLEL_INVOKE 1 |
| 28 | #define TBB_PREVIEW_FLOW_GRAPH_NODES 1 |
| 29 | #define TBB_PREVIEW_BLOCKED_RANGE_ND 1 |
| 30 | #define TBB_PREVIEW_WAITING_FOR_WORKERS 1 |
| 31 | #define TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS 1 |
| 32 | #endif |
| 33 | |
| 34 | #if __TBB_TEST_SECONDARY |
| 35 | // Test _DEBUG macro custom definitions. |
| 36 | #if TBB_USE_DEBUG |
| 37 | #ifdef _DEBUG |
| 38 | #undef _DEBUG |
| 39 | #endif /* _DEBUG */ |
| 40 | // Check that empty value successfully enables the debug mode. |
| 41 | #define _DEBUG |
| 42 | static bool isDebugExpected = true; |
| 43 | #else |
| 44 | // Check that zero value does not enable the debug mode. |
| 45 | #define _DEBUG 0x0 |
| 46 | static bool isDebugExpected = false; |
| 47 | #endif /* TBB_USE_DEBUG */ |
| 48 | #define DO_TEST_DEBUG_MACRO 1 |
| 49 | #else |
| 50 | // Test default definitions of _DEBUG. |
| 51 | #if _DEBUG |
| 52 | static bool isDebugExpected = true; |
| 53 | #define DO_TEST_DEBUG_MACRO 1 |
| 54 | #elif _MSC_VER |
| 55 | // for MSVC, _DEBUG not defined indicates a release mode. |
| 56 | static bool isDebugExpected = false; |
| 57 | #define DO_TEST_DEBUG_MACRO 1 |
| 58 | #endif /* _DEBUG */ |
| 59 | #endif /* __TBB_TEST_SECONDARY */ |
| 60 | |
| 61 | #if DO_TEST_DEBUG_MACRO |
| 62 | // Reset TBB_USE_DEBUG defined in makefiles. |
| 63 | #undef TBB_USE_DEBUG |
| 64 | #endif /* DO_TEST_DEBUG_MACRO */ |
| 65 | #define __TBB_CONFIG_PREPROC_ONLY _MSC_VER // For MSVC, prevent including standard headers in tbb_config.h |
| 66 | #include "tbb/tbb_config.h" |
| 67 | |
| 68 | #if !TBB_USE_DEBUG && defined(_DEBUG) |
| 69 | // TBB_USE_DEBUG is 0 but _DEBUG is defined, it means that _DEBUG is 0 |
| 70 | // MSVC C++ headers consider any definition of _DEBUG, including 0, as debug mode |
| 71 | #undef _DEBUG |
| 72 | #endif /* !TBB_USE_DEBUG && defined(_DEBUG) */ |
| 73 | |
| 74 | #include "harness_defs.h" |
| 75 | #if _MSC_VER |
| 76 | #pragma warning (disable : 4503) // decorated name length exceeded, name was truncated |
| 77 | #endif |
| 78 | |
| 79 | #if !(__TBB_TEST_SECONDARY && __TBB_CPP11_STD_PLACEHOLDERS_LINKAGE_BROKEN) |
| 80 | |
| 81 | #include "tbb/tbb.h" |
| 82 | |
| 83 | static volatile size_t g_sink; |
| 84 | |
| 85 | #define TestTypeDefinitionPresence( Type ) g_sink = sizeof(tbb::Type); |
| 86 | #define TestTypeDefinitionPresence2(TypeStart, TypeEnd) g_sink = sizeof(tbb::TypeStart,TypeEnd); |
| 87 | #define TestTypeDefinitionPresence3(TypeStart, TypeMid, TypeEnd) g_sink = sizeof(tbb::TypeStart,TypeMid,TypeEnd); |
| 88 | #define TestFuncDefinitionPresence(Fn, Args, ReturnType) { ReturnType (*pfn)Args = &tbb::Fn; (void)pfn; } |
| 89 | |
| 90 | struct Body { |
| 91 | void operator() () const {} |
| 92 | }; |
| 93 | struct Body1 { |
| 94 | void operator() ( int ) const {} |
| 95 | }; |
| 96 | struct Body1a { // feeder body for parallel_do |
| 97 | void operator() ( int, tbb::parallel_do_feeder<int>& ) const {} |
| 98 | }; |
| 99 | struct Body1b { // binary operator for reduction and comparison |
| 100 | int operator() ( const int, const int ) const { return 0; } |
| 101 | }; |
| 102 | struct Body2 { |
| 103 | Body2 () {} |
| 104 | Body2 ( const Body2&, tbb::split ) {} |
| 105 | void operator() ( const tbb::blocked_range<int>& ) const {} |
| 106 | void join( const Body2& ) {} |
| 107 | }; |
| 108 | struct Body2a { // for lambda-friendly parallel_reduce |
| 109 | int operator() ( const tbb::blocked_range<int>&, const int ) const { return 0; } |
| 110 | }; |
| 111 | struct Body3 { // for parallel_scan |
| 112 | Body3 () {} |
| 113 | Body3 ( const Body3&, tbb::split ) {} |
| 114 | void operator() ( const tbb::blocked_range2d<int>&, tbb::pre_scan_tag ) const {} |
| 115 | void operator() ( const tbb::blocked_range2d<int>&, tbb::final_scan_tag ) const {} |
| 116 | void reverse_join( Body3& ) {} |
| 117 | void assign( const Body3& ) {} |
| 118 | }; |
| 119 | struct Body3a { // for lambda-friednly parallel_scan |
| 120 | int operator() ( const tbb::blocked_range<int>&, const int, bool ) const { return 0; } |
| 121 | }; |
| 122 | struct Msg {}; |
| 123 | |
| 124 | #if !__TBB_TEST_SECONDARY |
| 125 | |
| 126 | #define HARNESS_NO_PARSE_COMMAND_LINE 1 |
| 127 | #include "harness.h" |
| 128 | |
| 129 | // Test if all the necessary symbols are exported for the exceptions thrown by TBB. |
| 130 | // Missing exports result either in link error or in runtime assertion failure. |
| 131 | #include <stdexcept> |
| 132 | |
| 133 | template <typename E> |
| 134 | void TestExceptionClassExports ( const E& exc, tbb::internal::exception_id eid ) { |
| 135 | // The assertion here serves to shut up warnings about "eid not used". |
| 136 | ASSERT( eid<tbb::internal::eid_max, NULL ); |
| 137 | #if TBB_USE_EXCEPTIONS |
| 138 | for ( int i = 0; i < 2; ++i ) { |
| 139 | try { |
| 140 | if ( i == 0 ) |
| 141 | throw exc; |
| 142 | #if !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN |
| 143 | else |
| 144 | tbb::internal::throw_exception( eid ); |
| 145 | #endif |
| 146 | } |
| 147 | catch ( E& e ) { |
| 148 | ASSERT ( e.what(), "Missing what() string" ); |
| 149 | } |
| 150 | catch ( ... ) { |
| 151 | ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception. Likely RTTI related exports are missing" ); |
| 152 | } |
| 153 | } |
| 154 | #else /* TBB_USE_EXCEPTIONS */ |
| 155 | (void)exc; |
| 156 | #endif /* TBB_USE_EXCEPTIONS */ |
| 157 | } |
| 158 | |
| 159 | void TestExceptionClassesExports () { |
| 160 | TestExceptionClassExports( std::bad_alloc(), tbb::internal::eid_bad_alloc ); |
| 161 | TestExceptionClassExports( tbb::bad_last_alloc(), tbb::internal::eid_bad_last_alloc ); |
| 162 | TestExceptionClassExports( std::invalid_argument("test" ), tbb::internal::eid_nonpositive_step ); |
| 163 | TestExceptionClassExports( std::out_of_range("test" ), tbb::internal::eid_out_of_range ); |
| 164 | TestExceptionClassExports( std::range_error("test" ), tbb::internal::eid_segment_range_error ); |
| 165 | TestExceptionClassExports( std::range_error("test" ), tbb::internal::eid_index_range_error ); |
| 166 | TestExceptionClassExports( tbb::missing_wait(), tbb::internal::eid_missing_wait ); |
| 167 | TestExceptionClassExports( tbb::invalid_multiple_scheduling(), tbb::internal::eid_invalid_multiple_scheduling ); |
| 168 | TestExceptionClassExports( tbb::improper_lock(), tbb::internal::eid_improper_lock ); |
| 169 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_possible_deadlock ); |
| 170 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_operation_not_permitted ); |
| 171 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_condvar_wait_failed ); |
| 172 | TestExceptionClassExports( std::out_of_range("test" ), tbb::internal::eid_invalid_load_factor ); |
| 173 | TestExceptionClassExports( std::invalid_argument("test" ), tbb::internal::eid_invalid_swap ); |
| 174 | TestExceptionClassExports( std::length_error("test" ), tbb::internal::eid_reservation_length_error ); |
| 175 | TestExceptionClassExports( std::out_of_range("test" ), tbb::internal::eid_invalid_key ); |
| 176 | TestExceptionClassExports( tbb::user_abort(), tbb::internal::eid_user_abort ); |
| 177 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_bad_tagged_msg_cast ); |
| 178 | } |
| 179 | #endif /* !__TBB_TEST_SECONDARY */ |
| 180 | |
| 181 | #if __TBB_CPF_BUILD |
| 182 | // These names are only tested in "preview" configuration |
| 183 | // When a feature becomes fully supported, its names should be moved to the main test |
| 184 | struct Handler { |
| 185 | void operator()( tbb::aggregator_operation* ) {} |
| 186 | }; |
| 187 | static void TestPreviewNames() { |
| 188 | TestTypeDefinitionPresence( aggregator ); |
| 189 | TestTypeDefinitionPresence( aggregator_ext<Handler> ); |
| 190 | #if __TBB_CPP11_PRESENT |
| 191 | TestTypeDefinitionPresence2(blocked_rangeNd<int,4> ); |
| 192 | #endif |
| 193 | TestTypeDefinitionPresence2(concurrent_lru_cache<int, int> ); |
| 194 | #if !__TBB_TEST_SECONDARY |
| 195 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_blocking_thread_join_impossible ); |
| 196 | #endif |
| 197 | #if __TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT |
| 198 | TestTypeDefinitionPresence2(concurrent_map<int, int> ); |
| 199 | TestTypeDefinitionPresence2(concurrent_multimap<int, int> ); |
| 200 | TestTypeDefinitionPresence(concurrent_set<int> ); |
| 201 | TestTypeDefinitionPresence(concurrent_multiset<int> ); |
| 202 | #endif |
| 203 | } |
| 204 | #endif |
| 205 | |
| 206 | #if __TBB_TEST_SECONDARY |
| 207 | /* This mode is used to produce a secondary object file that is linked with |
| 208 | the main one in order to detect "multiple definition" linker error. |
| 209 | */ |
| 210 | #include "harness_assert.h" |
| 211 | bool Secondary() |
| 212 | #else |
| 213 | bool Secondary(); |
| 214 | int TestMain () |
| 215 | #endif |
| 216 | { |
| 217 | #if __TBB_CPP11_STD_PLACEHOLDERS_LINKAGE_BROKEN |
| 218 | REPORT("Known issue: \"multiple definition\" linker error detection test skipped.\n" ); |
| 219 | #endif |
| 220 | TestTypeDefinitionPresence( aligned_space<int> ); |
| 221 | TestTypeDefinitionPresence( atomic<int> ); |
| 222 | TestTypeDefinitionPresence( cache_aligned_allocator<int> ); |
| 223 | TestTypeDefinitionPresence( tbb_hash_compare<int> ); |
| 224 | TestTypeDefinitionPresence2(concurrent_hash_map<int, int> ); |
| 225 | TestTypeDefinitionPresence2(concurrent_unordered_map<int, int> ); |
| 226 | TestTypeDefinitionPresence2(concurrent_unordered_multimap<int, int> ); |
| 227 | TestTypeDefinitionPresence( concurrent_unordered_set<int> ); |
| 228 | TestTypeDefinitionPresence( concurrent_unordered_multiset<int> ); |
| 229 | TestTypeDefinitionPresence( concurrent_bounded_queue<int> ); |
| 230 | TestTypeDefinitionPresence( concurrent_queue<int> ); |
| 231 | TestTypeDefinitionPresence( strict_ppl::concurrent_queue<int> ); |
| 232 | TestTypeDefinitionPresence( concurrent_priority_queue<int> ); |
| 233 | TestTypeDefinitionPresence( concurrent_vector<int> ); |
| 234 | TestTypeDefinitionPresence( combinable<int> ); |
| 235 | TestTypeDefinitionPresence( enumerable_thread_specific<int> ); |
| 236 | /* Flow graph names */ |
| 237 | TestTypeDefinitionPresence( flow::graph ); |
| 238 | TestTypeDefinitionPresence( flow::continue_msg ); |
| 239 | TestTypeDefinitionPresence2(flow::tagged_msg<int, int> ); |
| 240 | TestFuncDefinitionPresence( flow::make_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void ); |
| 241 | TestFuncDefinitionPresence( flow::remove_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void ); |
| 242 | typedef tbb::flow::tuple<int, int> intpair; |
| 243 | TestTypeDefinitionPresence( flow::source_node<int> ); |
| 244 | TestTypeDefinitionPresence3(flow::function_node<int, int, tbb::flow::rejecting> ); |
| 245 | TestTypeDefinitionPresence3(flow::multifunction_node<int, intpair, tbb::flow::queueing> ); |
| 246 | TestTypeDefinitionPresence3(flow::async_node<int, int, tbb::flow::queueing_lightweight> ); |
| 247 | TestTypeDefinitionPresence2(flow::continue_node<int, tbb::flow::lightweight> ); |
| 248 | TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::reserving> ); |
| 249 | TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::key_matching<int> > ); |
| 250 | TestTypeDefinitionPresence( flow::split_node<intpair> ); |
| 251 | TestTypeDefinitionPresence( flow::overwrite_node<int> ); |
| 252 | TestTypeDefinitionPresence( flow::write_once_node<int> ); |
| 253 | TestTypeDefinitionPresence( flow::broadcast_node<int> ); |
| 254 | TestTypeDefinitionPresence( flow::buffer_node<int> ); |
| 255 | TestTypeDefinitionPresence( flow::queue_node<int> ); |
| 256 | TestTypeDefinitionPresence( flow::sequencer_node<int> ); |
| 257 | TestTypeDefinitionPresence( flow::priority_queue_node<int> ); |
| 258 | TestTypeDefinitionPresence( flow::limiter_node<int> ); |
| 259 | TestTypeDefinitionPresence2(flow::indexer_node<int, int> ); |
| 260 | #if __TBB_FLOW_GRAPH_CPP11_FEATURES |
| 261 | TestTypeDefinitionPresence2(flow::composite_node<tbb::flow::tuple<int>, tbb::flow::tuple<int> > ); |
| 262 | #endif |
| 263 | /* Mutex names */ |
| 264 | TestTypeDefinitionPresence( mutex ); |
| 265 | TestTypeDefinitionPresence( null_mutex ); |
| 266 | TestTypeDefinitionPresence( null_rw_mutex ); |
| 267 | TestTypeDefinitionPresence( queuing_mutex ); |
| 268 | TestTypeDefinitionPresence( queuing_rw_mutex ); |
| 269 | TestTypeDefinitionPresence( recursive_mutex ); |
| 270 | TestTypeDefinitionPresence( spin_mutex ); |
| 271 | TestTypeDefinitionPresence( spin_rw_mutex ); |
| 272 | TestTypeDefinitionPresence( speculative_spin_mutex ); |
| 273 | TestTypeDefinitionPresence( speculative_spin_rw_mutex ); |
| 274 | TestTypeDefinitionPresence( critical_section ); |
| 275 | TestTypeDefinitionPresence( reader_writer_lock ); |
| 276 | #if __TBB_TASK_GROUP_CONTEXT |
| 277 | TestTypeDefinitionPresence( tbb_exception ); |
| 278 | TestTypeDefinitionPresence( captured_exception ); |
| 279 | TestTypeDefinitionPresence( movable_exception<int> ); |
| 280 | #if !TBB_USE_CAPTURED_EXCEPTION |
| 281 | TestTypeDefinitionPresence( internal::tbb_exception_ptr ); |
| 282 | #endif /* !TBB_USE_CAPTURED_EXCEPTION */ |
| 283 | TestTypeDefinitionPresence( task_group_context ); |
| 284 | TestTypeDefinitionPresence( task_group ); |
| 285 | TestTypeDefinitionPresence( structured_task_group ); |
| 286 | TestTypeDefinitionPresence( task_handle<Body> ); |
| 287 | #endif /* __TBB_TASK_GROUP_CONTEXT */ |
| 288 | /* Algorithm related names */ |
| 289 | TestTypeDefinitionPresence( blocked_range<int> ); |
| 290 | TestTypeDefinitionPresence( blocked_range2d<int> ); |
| 291 | TestTypeDefinitionPresence( blocked_range3d<int> ); |
| 292 | TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, const Body&), void ); |
| 293 | TestFuncDefinitionPresence( parallel_do, (int*, int*, const Body1&), void ); |
| 294 | TestFuncDefinitionPresence( parallel_for_each, (int*, int*, const Body1&), void ); |
| 295 | TestFuncDefinitionPresence( parallel_for, (int, int, int, const Body1&), void ); |
| 296 | TestFuncDefinitionPresence( parallel_for, (const tbb::blocked_range<int>&, const Body2&, const tbb::simple_partitioner&), void ); |
| 297 | TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int ); |
| 298 | TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::affinity_partitioner&), void ); |
| 299 | TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int ); |
| 300 | TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::static_partitioner&), void ); |
| 301 | TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range2d<int>&, Body3&, const tbb::auto_partitioner&), void ); |
| 302 | TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range<int>&, const int&, const Body3a&, const Body1b&), int ); |
| 303 | typedef int intarray[10]; |
| 304 | TestFuncDefinitionPresence( parallel_sort, (int*, int*), void ); |
| 305 | TestFuncDefinitionPresence( parallel_sort, (intarray&, const Body1b&), void ); |
| 306 | TestTypeDefinitionPresence( pipeline ); |
| 307 | TestFuncDefinitionPresence( parallel_pipeline, (size_t, const tbb::filter_t<void,void>&), void ); |
| 308 | #if __TBB_TASK_GROUP_CONTEXT |
| 309 | TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, tbb::task_group_context&), void ); |
| 310 | TestFuncDefinitionPresence( parallel_do, (const intarray&, const Body1a&, tbb::task_group_context&), void ); |
| 311 | TestFuncDefinitionPresence( parallel_for_each, (const intarray&, const Body1&, tbb::task_group_context&), void ); |
| 312 | TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, const tbb::auto_partitioner&, tbb::task_group_context&), void ); |
| 313 | TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, tbb::task_group_context&), void ); |
| 314 | TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::auto_partitioner&, tbb::task_group_context&), void ); |
| 315 | TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void ); |
| 316 | TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::simple_partitioner&, tbb::task_group_context&), void ); |
| 317 | TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void ); |
| 318 | #endif /* __TBB_TASK_GROUP_CONTEXT */ |
| 319 | TestTypeDefinitionPresence( proportional_split ); |
| 320 | |
| 321 | TestTypeDefinitionPresence( task ); |
| 322 | TestTypeDefinitionPresence( empty_task ); |
| 323 | TestTypeDefinitionPresence( task_list ); |
| 324 | TestTypeDefinitionPresence( task_arena ); |
| 325 | TestFuncDefinitionPresence( this_task_arena::current_thread_index, (), int ); |
| 326 | TestFuncDefinitionPresence( this_task_arena::max_concurrency, (), int ); |
| 327 | #if !__TBB_GCC_OVERLOADED_TEMPLATE_FUNCTION_ADDRESS_BROKEN |
| 328 | TestFuncDefinitionPresence( this_task_arena::isolate, (const Body&), void ); |
| 329 | #endif |
| 330 | TestTypeDefinitionPresence( task_scheduler_init ); |
| 331 | TestTypeDefinitionPresence( task_scheduler_observer ); |
| 332 | TestTypeDefinitionPresence( tbb_thread ); |
| 333 | TestFuncDefinitionPresence( tbb_thread::hardware_concurrency, (), unsigned ); |
| 334 | TestFuncDefinitionPresence( this_tbb_thread::yield, (), void ); |
| 335 | TestTypeDefinitionPresence( tbb_allocator<int> ); |
| 336 | TestTypeDefinitionPresence( zero_allocator<int> ); |
| 337 | TestTypeDefinitionPresence( tick_count ); |
| 338 | TestTypeDefinitionPresence( global_control ); |
| 339 | #if __TBB_CPP11_PRESENT |
| 340 | TestTypeDefinitionPresence( counting_iterator<int> ); |
| 341 | TestTypeDefinitionPresence2(zip_iterator<int*,int*> ); |
| 342 | #endif |
| 343 | |
| 344 | #if __TBB_CPF_BUILD |
| 345 | TestPreviewNames(); |
| 346 | #endif |
| 347 | #ifdef DO_TEST_DEBUG_MACRO |
| 348 | #if TBB_USE_DEBUG |
| 349 | ASSERT( isDebugExpected, "Debug mode is observed while release mode is expected." ); |
| 350 | #else |
| 351 | ASSERT( !isDebugExpected, "Release mode is observed while debug mode is expected." ); |
| 352 | #endif /* TBB_USE_DEBUG */ |
| 353 | #endif /* DO_TEST_DEBUG_MACRO */ |
| 354 | #if __TBB_TEST_SECONDARY |
| 355 | return true; |
| 356 | #else |
| 357 | TestExceptionClassesExports(); |
| 358 | Secondary(); |
| 359 | return Harness::Done; |
| 360 | #endif /* __TBB_TEST_SECONDARY */ |
| 361 | } |
| 362 | #endif //!(__TBB_TEST_SECONDARY && __TBB_CPP11_STD_PLACEHOLDERS_LINKING_BROKEN) |
| 363 | |