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