]> www.ginac.de Git - ginac.git/blob - m4/ax_cxx_compile_stdcxx.m4
[BUGFIX] Fix crash in parser.
[ginac.git] / m4 / ax_cxx_compile_stdcxx.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', '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 <bkoz@redhat.com>
31 #   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
32 #   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
33 #   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
34 #   Copyright (c) 2015 Paul Norman <penorman@mac.com>
35 #   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
36 #   Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
37 #   Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
38 #   Copyright (c) 2020 Jason Merrill <jason@redhat.com>
39 #   Copyright (c) 2021 Jörn Heusipp <osmanx@problemloesungsmaschine.de>
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
48 dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
49 dnl  (serial version number 13).
50
51 AC_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
159 dnl  Test body for checking C++11 support
160
161 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
162   _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
163 )
164
165 dnl  Test body for checking C++14 support
166
167 m4_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
172 dnl  Test body for checking C++17 support
173
174 m4_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
180 dnl  Test body for checking C++20 support
181
182 m4_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
190 dnl  Tests for new features in C++11
191
192 m4_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
211 namespace 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
485 dnl  Tests for new features in C++14
486
487 m4_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
502 namespace 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
609 dnl  Tests for new features in C++17
610
611 m4_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
630 namespace 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
991 dnl  Tests for new features in C++20
992
993 m4_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
1007 namespace 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 ]])