Home | History | Annotate | Download | only in m4
      1 # ===========================================================================
      2 #  https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
      3 # ===========================================================================
      4 #
      5 # SYNOPSIS
      6 #
      7 #   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
      8 #
      9 # DESCRIPTION
     10 #
     11 #   Check for baseline language coverage in the compiler for the specified
     12 #   version of the C++ standard.  If necessary, add switches to CXX and
     13 #   CXXCPP to enable support.  VERSION may be '11' (for the C++11 standard)
     14 #   or '14' (for the C++14 standard).
     15 #
     16 #   The second argument, if specified, indicates whether you insist on an
     17 #   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
     18 #   -std=c++11).  If neither is specified, you get whatever works, with
     19 #   preference for an extended mode.
     20 #
     21 #   The third argument, if specified 'mandatory' or if left unspecified,
     22 #   indicates that baseline support for the specified C++ standard is
     23 #   required and that the macro should error out if no mode with that
     24 #   support is found.  If specified 'optional', then configuration proceeds
     25 #   regardless, after defining HAVE_CXX${VERSION} if and only if a
     26 #   supporting mode is found.
     27 #
     28 # LICENSE
     29 #
     30 #   Copyright (c) 2008 Benjamin Kosnik <bkoz (a] redhat.com>
     31 #   Copyright (c) 2012 Zack Weinberg <zackw (a] panix.com>
     32 #   Copyright (c) 2013 Roy Stogner <roystgnr (a] ices.utexas.edu>
     33 #   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov (a] google.com>
     34 #   Copyright (c) 2015 Paul Norman <penorman (a] mac.com>
     35 #   Copyright (c) 2015 Moritz Klammler <moritz (a] klammler.eu>
     36 #   Copyright (c) 2016 Krzesimir Nowak <qdlacz (a] gmail.com>
     37 #
     38 #   Copying and distribution of this file, with or without modification, are
     39 #   permitted in any medium without royalty provided the copyright notice
     40 #   and this notice are preserved.  This file is offered as-is, without any
     41 #   warranty.
     42 
     43 #serial 7
     44 
     45 dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
     46 dnl  (serial version number 13).
     47 
     48 AX_REQUIRE_DEFINED([AC_MSG_WARN])
     49 AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
     50   m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
     51         [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
     52         [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
     53         [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
     54   m4_if([$2], [], [],
     55         [$2], [ext], [],
     56         [$2], [noext], [],
     57         [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
     58   m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
     59         [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
     60         [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
     61         [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
     62   AC_LANG_PUSH([C++])dnl
     63   ac_success=no
     64   AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
     65   ax_cv_cxx_compile_cxx$1,
     66   [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
     67     [ax_cv_cxx_compile_cxx$1=yes],
     68     [ax_cv_cxx_compile_cxx$1=no])])
     69   if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
     70     ac_success=yes
     71   fi
     72 
     73   m4_if([$2], [noext], [], [dnl
     74   if test x$ac_success = xno; then
     75     for alternative in ${ax_cxx_compile_alternatives}; do
     76       switch="-std=gnu++${alternative}"
     77       cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
     78       AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
     79                      $cachevar,
     80         [ac_save_CXX="$CXX"
     81          CXX="$CXX $switch"
     82          AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
     83           [eval $cachevar=yes],
     84           [eval $cachevar=no])
     85          CXX="$ac_save_CXX"])
     86       if eval test x\$$cachevar = xyes; then
     87         CXX="$CXX $switch"
     88         if test -n "$CXXCPP" ; then
     89           CXXCPP="$CXXCPP $switch"
     90         fi
     91         ac_success=yes
     92         break
     93       fi
     94     done
     95   fi])
     96 
     97   m4_if([$2], [ext], [], [dnl
     98   if test x$ac_success = xno; then
     99     dnl HP's aCC needs +std=c++11 according to:
    100     dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
    101     dnl Cray's crayCC needs "-h std=c++11"
    102     for alternative in ${ax_cxx_compile_alternatives}; do
    103       for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
    104         cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
    105         AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
    106                        $cachevar,
    107           [ac_save_CXX="$CXX"
    108            CXX="$CXX $switch"
    109            AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
    110             [eval $cachevar=yes],
    111             [eval $cachevar=no])
    112            CXX="$ac_save_CXX"])
    113         if eval test x\$$cachevar = xyes; then
    114           CXX="$CXX $switch"
    115           if test -n "$CXXCPP" ; then
    116             CXXCPP="$CXXCPP $switch"
    117           fi
    118           ac_success=yes
    119           break
    120         fi
    121       done
    122       if test x$ac_success = xyes; then
    123         break
    124       fi
    125     done
    126   fi])
    127   AC_LANG_POP([C++])
    128   if test x$ax_cxx_compile_cxx$1_required = xtrue; then
    129     if test x$ac_success = xno; then
    130       AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
    131     fi
    132   fi
    133   if test x$ac_success = xno; then
    134     HAVE_CXX$1=0
    135     AC_MSG_NOTICE([No compiler with C++$1 support was found])
    136   else
    137     HAVE_CXX$1=1
    138     AC_DEFINE(HAVE_CXX$1,1,
    139               [define if the compiler supports basic C++$1 syntax])
    140   fi
    141   AC_SUBST(HAVE_CXX$1)
    142   m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
    143 ])
    144 
    145 
    146 dnl  Test body for checking C++11 support
    147 
    148 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
    149   _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
    150 )
    151 
    152 
    153 dnl  Test body for checking C++14 support
    154 
    155 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
    156   _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
    157   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
    158 )
    159 
    160 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
    161   _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
    162   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
    163   _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
    164 )
    165 
    166 dnl  Tests for new features in C++11
    167 
    168 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
    169 
    170 // If the compiler admits that it is not ready for C++11, why torture it?
    171 // Hopefully, this will speed up the test.
    172 
    173 #ifndef __cplusplus
    174 
    175 #error "This is not a C++ compiler"
    176 
    177 #elif __cplusplus < 201103L
    178 
    179 #error "This is not a C++11 compiler"
    180 
    181 #else
    182 
    183 namespace cxx11
    184 {
    185 
    186   namespace test_static_assert
    187   {
    188 
    189     template <typename T>
    190     struct check
    191     {
    192       static_assert(sizeof(int) <= sizeof(T), "not big enough");
    193     };
    194 
    195   }
    196 
    197   namespace test_final_override
    198   {
    199 
    200     struct Base
    201     {
    202       virtual void f() {}
    203     };
    204 
    205     struct Derived : public Base
    206     {
    207       virtual void f() override {}
    208     };
    209 
    210   }
    211 
    212   namespace test_double_right_angle_brackets
    213   {
    214 
    215     template < typename T >
    216     struct check {};
    217 
    218     typedef check<void> single_type;
    219     typedef check<check<void>> double_type;
    220     typedef check<check<check<void>>> triple_type;
    221     typedef check<check<check<check<void>>>> quadruple_type;
    222 
    223   }
    224 
    225   namespace test_decltype
    226   {
    227 
    228     int
    229     f()
    230     {
    231       int a = 1;
    232       decltype(a) b = 2;
    233       return a + b;
    234     }
    235 
    236   }
    237 
    238   namespace test_type_deduction
    239   {
    240 
    241     template < typename T1, typename T2 >
    242     struct is_same
    243     {
    244       static const bool value = false;
    245     };
    246 
    247     template < typename T >
    248     struct is_same<T, T>
    249     {
    250       static const bool value = true;
    251     };
    252 
    253     template < typename T1, typename T2 >
    254     auto
    255     add(T1 a1, T2 a2) -> decltype(a1 + a2)
    256     {
    257       return a1 + a2;
    258     }
    259 
    260     int
    261     test(const int c, volatile int v)
    262     {
    263       static_assert(is_same<int, decltype(0)>::value == true, "");
    264       static_assert(is_same<int, decltype(c)>::value == false, "");
    265       static_assert(is_same<int, decltype(v)>::value == false, "");
    266       auto ac = c;
    267       auto av = v;
    268       auto sumi = ac + av + 'x';
    269       auto sumf = ac + av + 1.0;
    270       static_assert(is_same<int, decltype(ac)>::value == true, "");
    271       static_assert(is_same<int, decltype(av)>::value == true, "");
    272       static_assert(is_same<int, decltype(sumi)>::value == true, "");
    273       static_assert(is_same<int, decltype(sumf)>::value == false, "");
    274       static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
    275       return (sumf > 0.0) ? sumi : add(c, v);
    276     }
    277 
    278   }
    279 
    280   namespace test_noexcept
    281   {
    282 
    283     int f() { return 0; }
    284     int g() noexcept { return 0; }
    285 
    286     static_assert(noexcept(f()) == false, "");
    287     static_assert(noexcept(g()) == true, "");
    288 
    289   }
    290 
    291   namespace test_constexpr
    292   {
    293 
    294     template < typename CharT >
    295     unsigned long constexpr
    296     strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
    297     {
    298       return *s ? strlen_c_r(s + 1, acc + 1) : acc;
    299     }
    300 
    301     template < typename CharT >
    302     unsigned long constexpr
    303     strlen_c(const CharT *const s) noexcept
    304     {
    305       return strlen_c_r(s, 0UL);
    306     }
    307 
    308     static_assert(strlen_c("") == 0UL, "");
    309     static_assert(strlen_c("1") == 1UL, "");
    310     static_assert(strlen_c("example") == 7UL, "");
    311     static_assert(strlen_c("another\0example") == 7UL, "");
    312 
    313   }
    314 
    315   namespace test_rvalue_references
    316   {
    317 
    318     template < int N >
    319     struct answer
    320     {
    321       static constexpr int value = N;
    322     };
    323 
    324     answer<1> f(int&)       { return answer<1>(); }
    325     answer<2> f(const int&) { return answer<2>(); }
    326     answer<3> f(int&&)      { return answer<3>(); }
    327 
    328     void
    329     test()
    330     {
    331       int i = 0;
    332       const int c = 0;
    333       static_assert(decltype(f(i))::value == 1, "");
    334       static_assert(decltype(f(c))::value == 2, "");
    335       static_assert(decltype(f(0))::value == 3, "");
    336     }
    337 
    338   }
    339 
    340   namespace test_uniform_initialization
    341   {
    342 
    343     struct test
    344     {
    345       static const int zero {};
    346       static const int one {1};
    347     };
    348 
    349     static_assert(test::zero == 0, "");
    350     static_assert(test::one == 1, "");
    351 
    352   }
    353 
    354   namespace test_lambdas
    355   {
    356 
    357     void
    358     test1()
    359     {
    360       auto lambda1 = [](){};
    361       auto lambda2 = lambda1;
    362       lambda1();
    363       lambda2();
    364     }
    365 
    366     int
    367     test2()
    368     {
    369       auto a = [](int i, int j){ return i + j; }(1, 2);
    370       auto b = []() -> int { return '0'; }();
    371       auto c = [=](){ return a + b; }();
    372       auto d = [&](){ return c; }();
    373       auto e = [a, &b](int x) mutable {
    374         const auto identity = [](int y){ return y; };
    375         for (auto i = 0; i < a; ++i)
    376           a += b--;
    377         return x + identity(a + b);
    378       }(0);
    379       return a + b + c + d + e;
    380     }
    381 
    382     int
    383     test3()
    384     {
    385       const auto nullary = [](){ return 0; };
    386       const auto unary = [](int x){ return x; };
    387       using nullary_t = decltype(nullary);
    388       using unary_t = decltype(unary);
    389       const auto higher1st = [](nullary_t f){ return f(); };
    390       const auto higher2nd = [unary](nullary_t f1){
    391         return [unary, f1](unary_t f2){ return f2(unary(f1())); };
    392       };
    393       return higher1st(nullary) + higher2nd(nullary)(unary);
    394     }
    395 
    396   }
    397 
    398   namespace test_variadic_templates
    399   {
    400 
    401     template <int...>
    402     struct sum;
    403 
    404     template <int N0, int... N1toN>
    405     struct sum<N0, N1toN...>
    406     {
    407       static constexpr auto value = N0 + sum<N1toN...>::value;
    408     };
    409 
    410     template <>
    411     struct sum<>
    412     {
    413       static constexpr auto value = 0;
    414     };
    415 
    416     static_assert(sum<>::value == 0, "");
    417     static_assert(sum<1>::value == 1, "");
    418     static_assert(sum<23>::value == 23, "");
    419     static_assert(sum<1, 2>::value == 3, "");
    420     static_assert(sum<5, 5, 11>::value == 21, "");
    421     static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
    422 
    423   }
    424 
    425   // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
    426   // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
    427   // because of this.
    428   namespace test_template_alias_sfinae
    429   {
    430 
    431     struct foo {};
    432 
    433     template<typename T>
    434     using member = typename T::member_type;
    435 
    436     template<typename T>
    437     void func(...) {}
    438 
    439     template<typename T>
    440     void func(member<T>*) {}
    441 
    442     void test();
    443 
    444     void test() { func<foo>(0); }
    445 
    446   }
    447 
    448 }  // namespace cxx11
    449 
    450 #endif  // __cplusplus >= 201103L
    451 
    452 ]])
    453 
    454 
    455 dnl  Tests for new features in C++14
    456 
    457 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
    458 
    459 // If the compiler admits that it is not ready for C++14, why torture it?
    460 // Hopefully, this will speed up the test.
    461 
    462 #ifndef __cplusplus
    463 
    464 #error "This is not a C++ compiler"
    465 
    466 #elif __cplusplus < 201402L
    467 
    468 #error "This is not a C++14 compiler"
    469 
    470 #else
    471 
    472 namespace cxx14
    473 {
    474 
    475   namespace test_polymorphic_lambdas
    476   {
    477 
    478     int
    479     test()
    480     {
    481       const auto lambda = [](auto&&... args){
    482         const auto istiny = [](auto x){
    483           return (sizeof(x) == 1UL) ? 1 : 0;
    484         };
    485         const int aretiny[] = { istiny(args)... };
    486         return aretiny[0];
    487       };
    488       return lambda(1, 1L, 1.0f, '1');
    489     }
    490 
    491   }
    492 
    493   namespace test_binary_literals
    494   {
    495 
    496     constexpr auto ivii = 0b0000000000101010;
    497     static_assert(ivii == 42, "wrong value");
    498 
    499   }
    500 
    501   namespace test_generalized_constexpr
    502   {
    503 
    504     template < typename CharT >
    505     constexpr unsigned long
    506     strlen_c(const CharT *const s) noexcept
    507     {
    508       auto length = 0UL;
    509       for (auto p = s; *p; ++p)
    510         ++length;
    511       return length;
    512     }
    513 
    514     static_assert(strlen_c("") == 0UL, "");
    515     static_assert(strlen_c("x") == 1UL, "");
    516     static_assert(strlen_c("test") == 4UL, "");
    517     static_assert(strlen_c("another\0test") == 7UL, "");
    518 
    519   }
    520 
    521   namespace test_lambda_init_capture
    522   {
    523 
    524     int
    525     test()
    526     {
    527       auto x = 0;
    528       const auto lambda1 = [a = x](int b){ return a + b; };
    529       const auto lambda2 = [a = lambda1(x)](){ return a; };
    530       return lambda2();
    531     }
    532 
    533   }
    534 
    535   namespace test_digit_separators
    536   {
    537 
    538     constexpr auto ten_million = 100'000'000;
    539     static_assert(ten_million == 100000000, "");
    540 
    541   }
    542 
    543   namespace test_return_type_deduction
    544   {
    545 
    546     auto f(int& x) { return x; }
    547     decltype(auto) g(int& x) { return x; }
    548 
    549     template < typename T1, typename T2 >
    550     struct is_same
    551     {
    552       static constexpr auto value = false;
    553     };
    554 
    555     template < typename T >
    556     struct is_same<T, T>
    557     {
    558       static constexpr auto value = true;
    559     };
    560 
    561     int
    562     test()
    563     {
    564       auto x = 0;
    565       static_assert(is_same<int, decltype(f(x))>::value, "");
    566       static_assert(is_same<int&, decltype(g(x))>::value, "");
    567       return x;
    568     }
    569 
    570   }
    571 
    572 }  // namespace cxx14
    573 
    574 #endif  // __cplusplus >= 201402L
    575 
    576 ]])
    577 
    578 
    579 dnl  Tests for new features in C++17
    580 
    581 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
    582 
    583 // If the compiler admits that it is not ready for C++17, why torture it?
    584 // Hopefully, this will speed up the test.
    585 
    586 #ifndef __cplusplus
    587 
    588 #error "This is not a C++ compiler"
    589 
    590 #elif __cplusplus <= 201402L
    591 
    592 #error "This is not a C++17 compiler"
    593 
    594 #else
    595 
    596 #if defined(__clang__)
    597   #define REALLY_CLANG
    598 #else
    599   #if defined(__GNUC__)
    600     #define REALLY_GCC
    601   #endif
    602 #endif
    603 
    604 #include <initializer_list>
    605 #include <utility>
    606 #include <type_traits>
    607 
    608 namespace cxx17
    609 {
    610 
    611 #if !defined(REALLY_CLANG)
    612   namespace test_constexpr_lambdas
    613   {
    614 
    615     // TODO: test it with clang++ from git
    616 
    617     constexpr int foo = [](){return 42;}();
    618 
    619   }
    620 #endif // !defined(REALLY_CLANG)
    621 
    622   namespace test::nested_namespace::definitions
    623   {
    624 
    625   }
    626 
    627   namespace test_fold_expression
    628   {
    629 
    630     template<typename... Args>
    631     int multiply(Args... args)
    632     {
    633       return (args * ... * 1);
    634     }
    635 
    636     template<typename... Args>
    637     bool all(Args... args)
    638     {
    639       return (args && ...);
    640     }
    641 
    642   }
    643 
    644   namespace test_extended_static_assert
    645   {
    646 
    647     static_assert (true);
    648 
    649   }
    650 
    651   namespace test_auto_brace_init_list
    652   {
    653 
    654     auto foo = {5};
    655     auto bar {5};
    656 
    657     static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
    658     static_assert(std::is_same<int, decltype(bar)>::value);
    659   }
    660 
    661   namespace test_typename_in_template_template_parameter
    662   {
    663 
    664     template<template<typename> typename X> struct D;
    665 
    666   }
    667 
    668   namespace test_fallthrough_nodiscard_maybe_unused_attributes
    669   {
    670 
    671     int f1()
    672     {
    673       return 42;
    674     }
    675 
    676     [[nodiscard]] int f2()
    677     {
    678       [[maybe_unused]] auto unused = f1();
    679 
    680       switch (f1())
    681       {
    682       case 17:
    683         f1();
    684         [[fallthrough]];
    685       case 42:
    686         f1();
    687       }
    688       return f1();
    689     }
    690 
    691   }
    692 
    693   namespace test_extended_aggregate_initialization
    694   {
    695 
    696     struct base1
    697     {
    698       int b1, b2 = 42;
    699     };
    700 
    701     struct base2
    702     {
    703       base2() {
    704         b3 = 42;
    705       }
    706       int b3;
    707     };
    708 
    709     struct derived : base1, base2
    710     {
    711         int d;
    712     };
    713 
    714     derived d1 {{1, 2}, {}, 4};  // full initialization
    715     derived d2 {{}, {}, 4};      // value-initialized bases
    716 
    717   }
    718 
    719   namespace test_general_range_based_for_loop
    720   {
    721 
    722     struct iter
    723     {
    724       int i;
    725 
    726       int& operator* ()
    727       {
    728         return i;
    729       }
    730 
    731       const int& operator* () const
    732       {
    733         return i;
    734       }
    735 
    736       iter& operator++()
    737       {
    738         ++i;
    739         return *this;
    740       }
    741     };
    742 
    743     struct sentinel
    744     {
    745       int i;
    746     };
    747 
    748     bool operator== (const iter& i, const sentinel& s)
    749     {
    750       return i.i == s.i;
    751     }
    752 
    753     bool operator!= (const iter& i, const sentinel& s)
    754     {
    755       return !(i == s);
    756     }
    757 
    758     struct range
    759     {
    760       iter begin() const
    761       {
    762         return {0};
    763       }
    764 
    765       sentinel end() const
    766       {
    767         return {5};
    768       }
    769     };
    770 
    771     void f()
    772     {
    773       range r {};
    774 
    775       for (auto i : r)
    776       {
    777         [[maybe_unused]] auto v = i;
    778       }
    779     }
    780 
    781   }
    782 
    783   namespace test_lambda_capture_asterisk_this_by_value
    784   {
    785 
    786     struct t
    787     {
    788       int i;
    789       int foo()
    790       {
    791         return [*this]()
    792         {
    793           return i;
    794         }();
    795       }
    796     };
    797 
    798   }
    799 
    800   namespace test_enum_class_construction
    801   {
    802 
    803     enum class byte : unsigned char
    804     {};
    805 
    806     byte foo {42};
    807 
    808   }
    809 
    810   namespace test_constexpr_if
    811   {
    812 
    813     template <bool cond>
    814     int f ()
    815     {
    816       if constexpr(cond)
    817       {
    818         return 13;
    819       }
    820       else
    821       {
    822         return 42;
    823       }
    824     }
    825 
    826   }
    827 
    828   namespace test_selection_statement_with_initializer
    829   {
    830 
    831     int f()
    832     {
    833       return 13;
    834     }
    835 
    836     int f2()
    837     {
    838       if (auto i = f(); i > 0)
    839       {
    840         return 3;
    841       }
    842 
    843       switch (auto i = f(); i + 4)
    844       {
    845       case 17:
    846         return 2;
    847 
    848       default:
    849         return 1;
    850       }
    851     }
    852 
    853   }
    854 
    855 #if !defined(REALLY_CLANG)
    856   namespace test_template_argument_deduction_for_class_templates
    857   {
    858 
    859     // TODO: test it with clang++ from git
    860 
    861     template <typename T1, typename T2>
    862     struct pair
    863     {
    864       pair (T1 p1, T2 p2)
    865         : m1 {p1},
    866           m2 {p2}
    867       {}
    868 
    869       T1 m1;
    870       T2 m2;
    871     };
    872 
    873     void f()
    874     {
    875       [[maybe_unused]] auto p = pair{13, 42u};
    876     }
    877 
    878   }
    879 #endif // !defined(REALLY_CLANG)
    880 
    881   namespace test_non_type_auto_template_parameters
    882   {
    883 
    884     template <auto n>
    885     struct B
    886     {};
    887 
    888     B<5> b1;
    889     B<'a'> b2;
    890 
    891   }
    892 
    893 #if !defined(REALLY_CLANG)
    894   namespace test_structured_bindings
    895   {
    896 
    897     // TODO: test it with clang++ from git
    898 
    899     int arr[2] = { 1, 2 };
    900     std::pair<int, int> pr = { 1, 2 };
    901 
    902     auto f1() -> int(&)[2]
    903     {
    904       return arr;
    905     }
    906 
    907     auto f2() -> std::pair<int, int>&
    908     {
    909       return pr;
    910     }
    911 
    912     struct S
    913     {
    914       int x1 : 2;
    915       volatile double y1;
    916     };
    917 
    918     S f3()
    919     {
    920       return {};
    921     }
    922 
    923     auto [ x1, y1 ] = f1();
    924     auto& [ xr1, yr1 ] = f1();
    925     auto [ x2, y2 ] = f2();
    926     auto& [ xr2, yr2 ] = f2();
    927     const auto [ x3, y3 ] = f3();
    928 
    929   }
    930 #endif // !defined(REALLY_CLANG)
    931 
    932 #if !defined(REALLY_CLANG)
    933   namespace test_exception_spec_type_system
    934   {
    935 
    936     // TODO: test it with clang++ from git
    937 
    938     struct Good {};
    939     struct Bad {};
    940 
    941     void g1() noexcept;
    942     void g2();
    943 
    944     template<typename T>
    945     Bad
    946     f(T*, T*);
    947 
    948     template<typename T1, typename T2>
    949     Good
    950     f(T1*, T2*);
    951 
    952     static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
    953 
    954   }
    955 #endif // !defined(REALLY_CLANG)
    956 
    957   namespace test_inline_variables
    958   {
    959 
    960     template<class T> void f(T)
    961     {}
    962 
    963     template<class T> inline T g(T)
    964     {
    965       return T{};
    966     }
    967 
    968     template<> inline void f<>(int)
    969     {}
    970 
    971     template<> int g<>(int)
    972     {
    973       return 5;
    974     }
    975 
    976   }
    977 
    978 }  // namespace cxx17
    979 
    980 #endif  // __cplusplus <= 201402L
    981 
    982 ]])
    983