1# Copyright (c) 2016-2017 Free Software Foundation, Inc. 2# 3# Originally based on the AX_CXX_COMPILE_STDCXX macro found at the url 4# below. 5# 6# Local GDB customizations: 7# 8# - AC_SUBST CXX_DIALECT instead of changing CXX/CXXCPP. 9# 10# =========================================================================== 11# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html 12# =========================================================================== 13# 14# SYNOPSIS 15# 16# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) 17# 18# DESCRIPTION 19# 20# Check for baseline language coverage in the compiler for the specified 21# version of the C++ standard. If necessary, add switches to CXX and 22# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) 23# or '14' (for the C++14 standard). 24# 25# The second argument, if specified, indicates whether you insist on an 26# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. 27# -std=c++11). If neither is specified, you get whatever works, with 28# preference for an extended mode. 29# 30# The third argument, if specified 'mandatory' or if left unspecified, 31# indicates that baseline support for the specified C++ standard is 32# required and that the macro should error out if no mode with that 33# support is found. If specified 'optional', then configuration proceeds 34# regardless, after defining HAVE_CXX${VERSION} if and only if a 35# supporting mode is found. 36# 37# LICENSE 38# 39# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com> 40# Copyright (c) 2012 Zack Weinberg <zackw@panix.com> 41# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu> 42# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com> 43# Copyright (c) 2015 Paul Norman <penorman@mac.com> 44# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu> 45# 46# Copying and distribution of this file, with or without modification, are 47# permitted in any medium without royalty provided the copyright notice 48# and this notice are preserved. This file is offered as-is, without any 49# warranty. 50 51#serial 4 52 53dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro 54dnl (serial version number 13). 55 56AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl 57 m4_if([$1], [11], [], 58 [$1], [14], [], 59 [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], 60 [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl 61 m4_if([$2], [], [], 62 [$2], [ext], [], 63 [$2], [noext], [], 64 [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl 65 m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], 66 [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], 67 [$3], [optional], [ax_cxx_compile_cxx$1_required=false], 68 [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) 69 AC_LANG_PUSH([C++])dnl 70 CXX_DIALECT="" 71 ac_success=no 72 AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, 73 ax_cv_cxx_compile_cxx$1, 74 [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 75 [ax_cv_cxx_compile_cxx$1=yes], 76 [ax_cv_cxx_compile_cxx$1=no])]) 77 if test x$ax_cv_cxx_compile_cxx$1 = xyes; then 78 ac_success=yes 79 fi 80 81 m4_if([$2], [noext], [], [dnl 82 if test x$ac_success = xno; then 83 for switch in -std=gnu++$1 -std=gnu++0x; do 84 cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 85 AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 86 $cachevar, 87 [ac_save_CXX="$CXX" 88 CXX="$CXX $switch" 89 AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 90 [eval $cachevar=yes], 91 [eval $cachevar=no]) 92 CXX="$ac_save_CXX"]) 93 if eval test x\$$cachevar = xyes; then 94 CXX_DIALECT="$switch" 95 ac_success=yes 96 break 97 fi 98 done 99 fi]) 100 101 m4_if([$2], [ext], [], [dnl 102 if test x$ac_success = xno; then 103 dnl HP's aCC needs +std=c++11 according to: 104 dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf 105 dnl Cray's crayCC needs "-h std=c++11" 106 for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do 107 cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 108 AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 109 $cachevar, 110 [ac_save_CXX="$CXX" 111 CXX="$CXX $switch" 112 AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 113 [eval $cachevar=yes], 114 [eval $cachevar=no]) 115 CXX="$ac_save_CXX"]) 116 if eval test x\$$cachevar = xyes; then 117 CXX_DIALECT="$switch" 118 ac_success=yes 119 break 120 fi 121 done 122 fi]) 123 AC_LANG_POP([C++]) 124 if test x$ax_cxx_compile_cxx$1_required = xtrue; then 125 if test x$ac_success = xno; then 126 AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) 127 fi 128 fi 129 if test x$ac_success = xno; then 130 HAVE_CXX$1=0 131 AC_MSG_NOTICE([No compiler with C++$1 support was found]) 132 else 133 HAVE_CXX$1=1 134 AC_DEFINE(HAVE_CXX$1,1, 135 [define if the compiler supports basic C++$1 syntax]) 136 fi 137 AC_SUBST(HAVE_CXX$1) 138 AC_SUBST(CXX_DIALECT) 139]) 140 141 142dnl Test body for checking C++11 support 143 144m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], 145 _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 146) 147 148 149dnl Test body for checking C++14 support 150 151m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], 152 _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 153 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 154) 155 156 157dnl Tests for new features in C++11 158 159m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ 160 161// If the compiler admits that it is not ready for C++11, why torture it? 162// Hopefully, this will speed up the test. 163 164#ifndef __cplusplus 165 166#error "This is not a C++ compiler" 167 168#elif __cplusplus < 201103L 169 170#error "This is not a C++11 compiler" 171 172#else 173 174namespace cxx11 175{ 176 177 namespace test_static_assert 178 { 179 180 template <typename T> 181 struct check 182 { 183 static_assert(sizeof(int) <= sizeof(T), "not big enough"); 184 }; 185 186 } 187 188 namespace test_final_override 189 { 190 191 struct Base 192 { 193 virtual void f() {} 194 }; 195 196 struct Derived : public Base 197 { 198 virtual void f() override {} 199 }; 200 201 } 202 203 namespace test_double_right_angle_brackets 204 { 205 206 template < typename T > 207 struct check {}; 208 209 typedef check<void> single_type; 210 typedef check<check<void>> double_type; 211 typedef check<check<check<void>>> triple_type; 212 typedef check<check<check<check<void>>>> quadruple_type; 213 214 } 215 216 namespace test_decltype 217 { 218 219 int 220 f() 221 { 222 int a = 1; 223 decltype(a) b = 2; 224 return a + b; 225 } 226 227 } 228 229 namespace test_type_deduction 230 { 231 232 template < typename T1, typename T2 > 233 struct is_same 234 { 235 static const bool value = false; 236 }; 237 238 template < typename T > 239 struct is_same<T, T> 240 { 241 static const bool value = true; 242 }; 243 244 template < typename T1, typename T2 > 245 auto 246 add(T1 a1, T2 a2) -> decltype(a1 + a2) 247 { 248 return a1 + a2; 249 } 250 251 int 252 test(const int c, volatile int v) 253 { 254 static_assert(is_same<int, decltype(0)>::value == true, ""); 255 static_assert(is_same<int, decltype(c)>::value == false, ""); 256 static_assert(is_same<int, decltype(v)>::value == false, ""); 257 auto ac = c; 258 auto av = v; 259 auto sumi = ac + av + 'x'; 260 auto sumf = ac + av + 1.0; 261 static_assert(is_same<int, decltype(ac)>::value == true, ""); 262 static_assert(is_same<int, decltype(av)>::value == true, ""); 263 static_assert(is_same<int, decltype(sumi)>::value == true, ""); 264 static_assert(is_same<int, decltype(sumf)>::value == false, ""); 265 static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); 266 return (sumf > 0.0) ? sumi : add(c, v); 267 } 268 269 } 270 271 namespace test_noexcept 272 { 273 274 int f() { return 0; } 275 int g() noexcept { return 0; } 276 277 static_assert(noexcept(f()) == false, ""); 278 static_assert(noexcept(g()) == true, ""); 279 280 } 281 282 namespace test_constexpr 283 { 284 285 template < typename CharT > 286 unsigned long constexpr 287 strlen_c_r(const CharT *const s, const unsigned long acc) noexcept 288 { 289 return *s ? strlen_c_r(s + 1, acc + 1) : acc; 290 } 291 292 template < typename CharT > 293 unsigned long constexpr 294 strlen_c(const CharT *const s) noexcept 295 { 296 return strlen_c_r(s, 0UL); 297 } 298 299 static_assert(strlen_c("") == 0UL, ""); 300 static_assert(strlen_c("1") == 1UL, ""); 301 static_assert(strlen_c("example") == 7UL, ""); 302 static_assert(strlen_c("another\0example") == 7UL, ""); 303 304 } 305 306 namespace test_rvalue_references 307 { 308 309 template < int N > 310 struct answer 311 { 312 static constexpr int value = N; 313 }; 314 315 answer<1> f(int&) { return answer<1>(); } 316 answer<2> f(const int&) { return answer<2>(); } 317 answer<3> f(int&&) { return answer<3>(); } 318 319 void 320 test() 321 { 322 int i = 0; 323 const int c = 0; 324 static_assert(decltype(f(i))::value == 1, ""); 325 static_assert(decltype(f(c))::value == 2, ""); 326 static_assert(decltype(f(0))::value == 3, ""); 327 } 328 329 } 330 331 namespace test_uniform_initialization 332 { 333 334 struct test 335 { 336 static const int zero {}; 337 static const int one {1}; 338 }; 339 340 static_assert(test::zero == 0, ""); 341 static_assert(test::one == 1, ""); 342 343 } 344 345 namespace test_lambdas 346 { 347 348 void 349 test1() 350 { 351 auto lambda1 = [](){}; 352 auto lambda2 = lambda1; 353 lambda1(); 354 lambda2(); 355 } 356 357 int 358 test2() 359 { 360 auto a = [](int i, int j){ return i + j; }(1, 2); 361 auto b = []() -> int { return '0'; }(); 362 auto c = [=](){ return a + b; }(); 363 auto d = [&](){ return c; }(); 364 auto e = [a, &b](int x) mutable { 365 const auto identity = [](int y){ return y; }; 366 for (auto i = 0; i < a; ++i) 367 a += b--; 368 return x + identity(a + b); 369 }(0); 370 return a + b + c + d + e; 371 } 372 373 int 374 test3() 375 { 376 const auto nullary = [](){ return 0; }; 377 const auto unary = [](int x){ return x; }; 378 using nullary_t = decltype(nullary); 379 using unary_t = decltype(unary); 380 const auto higher1st = [](nullary_t f){ return f(); }; 381 const auto higher2nd = [unary](nullary_t f1){ 382 return [unary, f1](unary_t f2){ return f2(unary(f1())); }; 383 }; 384 return higher1st(nullary) + higher2nd(nullary)(unary); 385 } 386 387 } 388 389 namespace test_variadic_templates 390 { 391 392 template <int...> 393 struct sum; 394 395 template <int N0, int... N1toN> 396 struct sum<N0, N1toN...> 397 { 398 static constexpr auto value = N0 + sum<N1toN...>::value; 399 }; 400 401 template <> 402 struct sum<> 403 { 404 static constexpr auto value = 0; 405 }; 406 407 static_assert(sum<>::value == 0, ""); 408 static_assert(sum<1>::value == 1, ""); 409 static_assert(sum<23>::value == 23, ""); 410 static_assert(sum<1, 2>::value == 3, ""); 411 static_assert(sum<5, 5, 11>::value == 21, ""); 412 static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); 413 414 } 415 416 // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae 417 // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function 418 // because of this. 419 namespace test_template_alias_sfinae 420 { 421 422 struct foo {}; 423 424 template<typename T> 425 using member = typename T::member_type; 426 427 template<typename T> 428 void func(...) {} 429 430 template<typename T> 431 void func(member<T>*) {} 432 433 void test(); 434 435 void test() { func<foo>(0); } 436 437 } 438 439} // namespace cxx11 440 441#endif // __cplusplus >= 201103L 442 443]]) 444 445 446dnl Tests for new features in C++14 447 448m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ 449 450// If the compiler admits that it is not ready for C++14, why torture it? 451// Hopefully, this will speed up the test. 452 453#ifndef __cplusplus 454 455#error "This is not a C++ compiler" 456 457#elif __cplusplus < 201402L 458 459#error "This is not a C++14 compiler" 460 461#else 462 463namespace cxx14 464{ 465 466 namespace test_polymorphic_lambdas 467 { 468 469 int 470 test() 471 { 472 const auto lambda = [](auto&&... args){ 473 const auto istiny = [](auto x){ 474 return (sizeof(x) == 1UL) ? 1 : 0; 475 }; 476 const int aretiny[] = { istiny(args)... }; 477 return aretiny[0]; 478 }; 479 return lambda(1, 1L, 1.0f, '1'); 480 } 481 482 } 483 484 namespace test_binary_literals 485 { 486 487 constexpr auto ivii = 0b0000000000101010; 488 static_assert(ivii == 42, "wrong value"); 489 490 } 491 492 namespace test_generalized_constexpr 493 { 494 495 template < typename CharT > 496 constexpr unsigned long 497 strlen_c(const CharT *const s) noexcept 498 { 499 auto length = 0UL; 500 for (auto p = s; *p; ++p) 501 ++length; 502 return length; 503 } 504 505 static_assert(strlen_c("") == 0UL, ""); 506 static_assert(strlen_c("x") == 1UL, ""); 507 static_assert(strlen_c("test") == 4UL, ""); 508 static_assert(strlen_c("another\0test") == 7UL, ""); 509 510 } 511 512 namespace test_lambda_init_capture 513 { 514 515 int 516 test() 517 { 518 auto x = 0; 519 const auto lambda1 = [a = x](int b){ return a + b; }; 520 const auto lambda2 = [a = lambda1(x)](){ return a; }; 521 return lambda2(); 522 } 523 524 } 525 526 namespace test_digit_seperators 527 { 528 529 constexpr auto ten_million = 100'000'000; 530 static_assert(ten_million == 100000000, ""); 531 532 } 533 534 namespace test_return_type_deduction 535 { 536 537 auto f(int& x) { return x; } 538 decltype(auto) g(int& x) { return x; } 539 540 template < typename T1, typename T2 > 541 struct is_same 542 { 543 static constexpr auto value = false; 544 }; 545 546 template < typename T > 547 struct is_same<T, T> 548 { 549 static constexpr auto value = true; 550 }; 551 552 int 553 test() 554 { 555 auto x = 0; 556 static_assert(is_same<int, decltype(f(x))>::value, ""); 557 static_assert(is_same<int&, decltype(g(x))>::value, ""); 558 return x; 559 } 560 561 } 562 563} // namespace cxx14 564 565#endif // __cplusplus >= 201402L 566 567]]) 568