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