view m4/prog_cxx.m4 @ 21304:0cf6c08cb252

configure.ac: check support for C11 and C++11 (patch #8906) * configure.ac: two new checks for support of C++11 and C11 versions of the standard and to add required flags to CXX and CC. These need to be done before AC_PROG_CPP and AC_PROG_CXXPP since the later will make use of the defined CXX and CC. * m4/prog_c.m4, m4/prog_cxx.m4: added files for OCTAVE_PROG_CC_C11 and OCTAVE_PROG_CXX_CXX11 which are copied from autoconf source tree implementations of _AC_PROG_CC_C11 and _AC_PROG_CXX_CXX11.
author Carnë Draug <carandraug@octave.org>
date Thu, 18 Feb 2016 16:20:49 +0000
parents
children fd4ff31b3eed
line wrap: on
line source

# Copyright (C) 2001-2016 Free Software Foundation, Inc.
#
#
# This is pretty much copy and paste of the unreleased autoconf macros
# (where it is named AC_PROG_CC_C11).  Once we are dependent on
# autoconf version with that macro, we can simply change to use that
# one instead.  Copied from autoconf commit 04be2b7a (2016/02/06)
#
#
# This file is part of Autoconf.  This program is free
# software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.

# OCTAVE_PROG_CXX_CXX11 ([ACTION-IF-AVAILABLE], [ACTION-IF-UNAVAILABLE])
# -------------------------------------------------------------------
# If the C++ compiler is not in ISO CXX11 mode by default, try to add
# an option to output variable CXX to make it so.  This macro tries
# various options that select ISO C++11 on some system or another.  It
# considers the compiler to be in ISO C++11 mode if it handles all the
# tests from the C++98 checks, plus the following: Language features
# (auto, constexpr, decltype, default/deleted constructors, delegate
# constructors, final, initialiser lists, lambda functions, nullptr,
# override, range-based for loops, template brackets without spaces,
# unicode literals) and library features (array, memory (shared_ptr,
# weak_ptr), regex and tuple types).
AC_DEFUN([OCTAVE_PROG_CXX_CXX11],
[OCTAVE_CXX_STD_TRY([cxx11],
[OCTAVE_CXX_CXX11_TEST_HEADER
OCTAVE_CXX_CXX98_TEST_HEADER],
[OCTAVE_CXX_CXX11_TEST_BODY
OCTAVE_CXX_CXX98_TEST_BODY],
dnl Try
dnl GCC		-std=gnu++11 (unused restrictive mode: -std=c++11) [and 0x variants]
dnl IBM XL C	-qlanglvl=extended0x
dnl		(pre-V12.1; unused restrictive mode: -qlanglvl=stdcxx11)
dnl HP aC++	-AA
dnl Intel ICC	-std=c++11 -std=c++0x
dnl Solaris	N/A (no support)
dnl Tru64	N/A (no support)
dnl with extended modes being tried first.
[[-std=gnu++11 -std=c++11 -std=gnu++0x -std=c++0x -qlanglvl=extended0x -AA]], [$1], [$2])[]dnl
])# OCTAVE_PROG_CXX_CXX11


# OCTAVE_CXX_STD_TRY(STANDARD, TEST-PROLOGUE, TEST-BODY, OPTION-LIST,
#		  ACTION-IF-AVAILABLE, ACTION-IF-UNAVAILABLE)
# ----------------------------------------------------------------
# Check whether the C++ compiler accepts features of STANDARD (e.g
# `cxx98', `cxx11') by trying to compile a program of TEST-PROLOGUE
# and TEST-BODY.  If this fails, try again with each compiler option
# in the space-separated OPTION-LIST; if one helps, append it to CXX.
# If eventually successful, run ACTION-IF-AVAILABLE, else
# ACTION-IF-UNAVAILABLE.
AC_DEFUN([OCTAVE_CXX_STD_TRY],
[AC_MSG_CHECKING([for $CXX option to enable ]m4_translit(m4_translit($1, [x], [+]), [a-z], [A-Z])[ features])
AC_LANG_PUSH(C++)dnl
AC_CACHE_VAL(ac_cv_prog_cxx_$1,
[ac_cv_prog_cxx_$1=no
ac_save_CXX=$CXX
AC_LANG_CONFTEST([AC_LANG_PROGRAM([$2], [$3])])
for ac_arg in '' $4
do
  CXX="$ac_save_CXX $ac_arg"
  _AC_COMPILE_IFELSE([], [ac_cv_prog_cxx_$1=$ac_arg])
  test "x$ac_cv_prog_cxx_$1" != "xno" && break
done
rm -f conftest.$ac_ext
CXX=$ac_save_CXX
])# AC_CACHE_VAL
ac_prog_cxx_stdcxx_options=
case "x$ac_cv_prog_cxx_$1" in
  x)
    AC_MSG_RESULT([none needed]) ;;
  xno)
    AC_MSG_RESULT([unsupported]) ;;
  *)
    ac_prog_cxx_stdcxx_options=" $ac_cv_prog_cxx_$1"
    CXX=$CXX$ac_prog_cxx_stdcxx_options
    AC_MSG_RESULT([$ac_cv_prog_cxx_$1]) ;;
esac
AC_LANG_POP(C++)dnl
AS_IF([test "x$ac_cv_prog_cxx_$1" != xno], [$5], [$6])
])# OCTAVE_CXX_STD_TRY

# OCTAVE_CXX_CXX98_TEST_HEADER
# -------------------------
# A C++ header suitable for testing for CXX98.
AC_DEFUN([OCTAVE_CXX_CXX98_TEST_HEADER],
[[
#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>

namespace test {
  typedef std::vector<std::string> string_vec;
  typedef std::pair<int,bool> map_value;
  typedef std::map<std::string,map_value> map_type;
  typedef std::set<int> set_type;

  template<typename T>
  class printer {
  public:
    printer(std::ostringstream& os): os(os) {}
    void operator() (T elem) { os << elem << std::endl; }
  private:
    std::ostringstream& os;
  };
}
]])# OCTAVE_CXX_CXX98_TEST_HEADER

# OCTAVE_CXX_CXX98_TEST_BODY
# -----------------------
# A C++ body suitable for testing for CXX98, assuming the corresponding header.
AC_DEFUN([OCTAVE_CXX_CXX98_TEST_BODY],
[[

try {
  // Basic string.
  std::string teststr("ASCII text");
  teststr += " string";

  // Simple vector.
  test::string_vec testvec;
  testvec.push_back(teststr);
  testvec.push_back("foo");
  testvec.push_back("bar");
  if (testvec.size() != 3) {
    throw std::runtime_error("vector size is not 1");
  }

  // Dump vector into stringstream and obtain string.
  std::ostringstream os;
  for (test::string_vec::const_iterator i = testvec.begin();
       i != testvec.end(); ++i) {
    if (i + 1 != testvec.end()) {
      os << teststr << '\n';
    }
  }
  // Check algorithms work.
  std::for_each(testvec.begin(), testvec.end(), test::printer<std::string>(os));
  std::string os_out = os.str();

  // Test pair and map.
  test::map_type testmap;
  testmap.insert(std::make_pair(std::string("key"),
                                std::make_pair(53,false)));

  // Test set.
  int values[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
  test::set_type testset(values, values + sizeof(values)/sizeof(values[0]));
  std::list<int> testlist(testset.begin(), testset.end());
  std::copy(testset.begin(), testset.end(), std::back_inserter(testlist));
} catch (const std::exception& e) {
  std::cerr << "Caught exception: " << e.what() << std::endl;

  // Test fstream
  std::ofstream of("test.txt");
  of << "Test ASCII text\n" << std::flush;
  of << "N= " << std::hex << std::setw(8) << std::left << 534 << std::endl;
  of.close();
}
std::exit(0);
]])


# OCTAVE_CXX_CXX11_TEST_HEADER
# -------------------------
# A C++ header suitable for testing for CXX11.
AC_DEFUN([OCTAVE_CXX_CXX11_TEST_HEADER],
[[
#include <deque>
#include <functional>
#include <memory>
#include <tuple>
#include <array>
#include <regex>
#include <iostream>

namespace cxx11test
{
  typedef std::shared_ptr<std::string> sptr;
  typedef std::weak_ptr<std::string> wptr;

  typedef std::tuple<std::string,int,double> tp;
  typedef std::array<int, 20> int_array;

  constexpr int get_val() { return 20; }

  struct testinit
  {
    int i;
    double d;
  };

  class delegate  {
  public:
    delegate(int n) : n(n) {}
    delegate(): delegate(2354) {}

    virtual int getval() { return this->n; };
  protected:
    int n;
  };

  class overridden : public delegate {
  public:
    overridden(int n): delegate(n) {}
    virtual int getval() override final { return this->n * 2; }
  };

  class nocopy {
  public:
    nocopy(int i): i(i) {}
    nocopy() = default;
    nocopy(const nocopy&) = delete;
    nocopy & operator=(const nocopy&) = delete;
  private:
    int i;
  };
}
]])# OCTAVE_CXX_CXX11_TEST_HEADER

# OCTAVE_CXX_CXX11_TEST_BODY
# -----------------------
# A C++ body suitable for testing for CXX11, assuming the corresponding header.
AC_DEFUN([OCTAVE_CXX_CXX11_TEST_BODY],
[[
{
  // Test auto and decltype
  std::deque<int> d;
  d.push_front(43);
  d.push_front(484);
  d.push_front(3);
  d.push_front(844);
  int total = 0;
  for (auto i = d.begin(); i != d.end(); ++i) { total += *i; }

  auto a1 = 6538;
  auto a2 = 48573953.4;
  auto a3 = "String literal";

  decltype(a2) a4 = 34895.034;
}
{
  // Test constexpr
  short sa[cxx11test::get_val()] = { 0 };
}
{
  // Test initialiser lists
  cxx11test::testinit il = { 4323, 435234.23544 };
}
{
  // Test range-based for and lambda
  cxx11test::int_array array = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
  for (int &x : array) { x += 23; }
  std::for_each(array.begin(), array.end(), [](int v1){ std::cout << v1; });
}
{
  using cxx11test::sptr;
  using cxx11test::wptr;

  sptr sp(new std::string("ASCII string"));
  wptr wp(sp);
  sptr sp2(wp);
}
{
  cxx11test::tp tuple("test", 54, 45.53434);
  double d = std::get<2>(tuple);
  std::string s;
  int i;
  std::tie(s,i,d) = tuple;
}
{
  static std::regex filename_regex("^_?([a-z0-9_.]+-)+[a-z0-9]+$");
  std::string testmatch("Test if this string matches");
  bool match = std::regex_search(testmatch, filename_regex);
}
{
  cxx11test::int_array array = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
  cxx11test::int_array::size_type size = array.size();
}
{
  // Test constructor delegation
  cxx11test::delegate d1;
  cxx11test::delegate d2();
  cxx11test::delegate d3(45);
}
{
  // Test override and final
  cxx11test::overridden o1(55464);
}
{
  // Test nullptr
  char *c = nullptr;
}
{
  // Test template brackets
  std::vector<std::pair<int,char*>> v1;
}
{
  // Unicode literals
  char *utf8 = u8"UTF-8 string \u2500";
  char16_t *utf16 = u"UTF-8 string \u2500";
  char32_t *utf32 = U"UTF-32 string \u2500";
}
]])