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