build: require clang >= 4.0, Xcode >= 9.0

Also, recommend using gcc 7.4.0 or later, and silence
an ABI-related diagnostic message from gcc on armv7

Refs: #5087, #5106
Change-Id: I4d9841bea9df19cbb9ba3b0865949b1d66e6ec3e
diff --git a/.travis.yml b/.travis.yml
index 569f3f4..ab3e066 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,7 +18,10 @@
 jobs:
   include:
     # Linux
+    - env: COMPILER=g++-5
+    - env: COMPILER=g++-6
     - env: COMPILER=g++-8
+    - env: COMPILER=clang++-4.0
     - env: COMPILER=clang++-5.0
     - env: COMPILER=clang++-7
     - env: COMPILER=clang++-8
@@ -38,8 +41,14 @@
     - os: osx
       osx_image: xcode11.3
       env: # default compiler
+    - os: osx
+      osx_image: xcode11.4
+      env: # default compiler
 
   allow_failures:
+    - env: COMPILER=g++-5
+    - env: COMPILER=g++-6
+    - env: COMPILER=clang++-4.0
     - env: COMPILER=clang++-11
 
   fast_finish: true
diff --git a/.waf-tools/default-compiler-flags.py b/.waf-tools/default-compiler-flags.py
index 9e045c3..f3be6e7 100644
--- a/.waf-tools/default-compiler-flags.py
+++ b/.waf-tools/default-compiler-flags.py
@@ -1,10 +1,11 @@
 # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
+import platform
 from waflib import Configure, Logs, Utils
 
 def options(opt):
     opt.add_option('--debug', '--with-debug', action='store_true', default=False,
-                   help='Compile in debugging mode with minimal optimizations (-O0 or -Og)')
+                   help='Compile in debugging mode with minimal optimizations (-Og)')
 
 def configure(conf):
     conf.start_msg('Checking C++ compiler version')
@@ -17,15 +18,21 @@
     if cxx == 'gcc':
         if ccver < (5, 3, 0):
             errmsg = ('The version of gcc you are using is too old.\n'
-                      'The minimum supported gcc version is 5.3.0.')
+                      'The minimum supported gcc version is 7.4.0.')
+        elif ccver < (7, 4, 0):
+            warnmsg = ('Using a version of gcc older than 7.4.0 is not '
+                       'officially supported and may result in build failures.')
         conf.flags = GccFlags()
     elif cxx == 'clang':
-        if ccver < (3, 6, 0):
+        if Utils.unversioned_sys_platform() == 'darwin' and ccver < (9, 0, 0):
+            errmsg = ('The version of Xcode you are using is too old.\n'
+                      'The minimum supported Xcode version is 9.0.')
+        elif ccver < (4, 0, 0):
             errmsg = ('The version of clang you are using is too old.\n'
-                      'The minimum supported clang version is 3.6.0.')
+                      'The minimum supported clang version is 4.0.')
         conf.flags = ClangFlags()
     else:
-        warnmsg = 'Note: %s compiler is unsupported' % cxx
+        warnmsg = '%s compiler is unsupported' % cxx
         conf.flags = CompilerFlags()
 
     if errmsg:
@@ -33,7 +40,7 @@
         conf.fatal(errmsg)
     elif warnmsg:
         conf.end_msg(ccverstr, color='YELLOW')
-        Logs.warn(warnmsg)
+        Logs.warn('WARNING: ' + warnmsg)
     else:
         conf.end_msg(ccverstr)
 
@@ -137,13 +144,14 @@
 
     def getDebugFlags(self, conf):
         flags = super(GccBasicFlags, self).getDebugFlags(conf)
-        flags['CXXFLAGS'] += ['-O0',
-                              '-Og', # gcc >= 4.8, clang >= 4.0
+        flags['CXXFLAGS'] += ['-Og',
                               '-g3',
                               '-pedantic',
                               '-Wall',
                               '-Wextra',
                               '-Werror',
+                              '-Wcatch-value=2',
+                              '-Wextra-semi',
                               '-Wnon-virtual-dtor',
                               '-Wno-error=deprecated-declarations', # Bug #3795
                               '-Wno-error=maybe-uninitialized', # Bug #1615
@@ -159,6 +167,8 @@
                               '-pedantic',
                               '-Wall',
                               '-Wextra',
+                              '-Wcatch-value=2',
+                              '-Wextra-semi',
                               '-Wnon-virtual-dtor',
                               '-Wno-unused-parameter',
                               ]
@@ -168,49 +178,50 @@
 class GccFlags(GccBasicFlags):
     def getDebugFlags(self, conf):
         flags = super(GccFlags, self).getDebugFlags(conf)
-        flags['CXXFLAGS'] += ['-fdiagnostics-color']
+        flags['CXXFLAGS'] += ['-fdiagnostics-color',
+                              '-Wredundant-tags',
+                              ]
+        if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
+            flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
         return flags
 
     def getOptimizedFlags(self, conf):
         flags = super(GccFlags, self).getOptimizedFlags(conf)
-        flags['CXXFLAGS'] += ['-fdiagnostics-color']
+        flags['CXXFLAGS'] += ['-fdiagnostics-color',
+                              '-Wredundant-tags',
+                              ]
+        if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
+            flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
         return flags
 
 class ClangFlags(GccBasicFlags):
     def getGeneralFlags(self, conf):
         flags = super(ClangFlags, self).getGeneralFlags(conf)
-        if Utils.unversioned_sys_platform() == 'darwin' and self.getCompilerVersion(conf) >= (9, 0, 0):
+        if Utils.unversioned_sys_platform() == 'darwin':
             # Bug #4296
             flags['CXXFLAGS'] += [['-isystem', '/usr/local/include'], # for Homebrew
                                   ['-isystem', '/opt/local/include']] # for MacPorts
-        if Utils.unversioned_sys_platform() == 'freebsd':
-            flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']] # Bug #4790
+        elif Utils.unversioned_sys_platform() == 'freebsd':
+            # Bug #4790
+            flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']]
         return flags
 
     def getDebugFlags(self, conf):
         flags = super(ClangFlags, self).getDebugFlags(conf)
         flags['CXXFLAGS'] += ['-fcolor-diagnostics',
-                              '-Wextra-semi',
                               '-Wundefined-func-template',
                               '-Wno-unused-local-typedef', # Bugs #2657 and #3209
                               ]
-        version = self.getCompilerVersion(conf)
-        if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
-            flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
-        if version < (6, 0, 0):
+        if self.getCompilerVersion(conf) < (6, 0, 0):
             flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
         return flags
 
     def getOptimizedFlags(self, conf):
         flags = super(ClangFlags, self).getOptimizedFlags(conf)
         flags['CXXFLAGS'] += ['-fcolor-diagnostics',
-                              '-Wextra-semi',
                               '-Wundefined-func-template',
                               '-Wno-unused-local-typedef', # Bugs #2657 and #3209
                               ]
-        version = self.getCompilerVersion(conf)
-        if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
-            flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
-        if version < (6, 0, 0):
+        if self.getCompilerVersion(conf) < (6, 0, 0):
             flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
         return flags
diff --git a/docs/INSTALL.rst b/docs/INSTALL.rst
index 9de5b90..f893d1a 100644
--- a/docs/INSTALL.rst
+++ b/docs/INSTALL.rst
@@ -29,7 +29,8 @@
 Required
 ~~~~~~~~
 
--  GCC >= 5.3 or clang >= 3.6
+-  GCC >= 7.4 or clang >= 4.0 (on Linux and FreeBSD)
+-  Xcode >= 9.0 (on macOS)
 -  Python >= 3.6
 -  pkg-config
 -  Boost >= 1.65.1
diff --git a/ndn-cxx/lp/field.hpp b/ndn-cxx/lp/field.hpp
index ea1d4b4..6ae7465 100644
--- a/ndn-cxx/lp/field.hpp
+++ b/ndn-cxx/lp/field.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -63,8 +63,8 @@
   static_assert(std::is_base_of<field_location_tags::Base, typename X::FieldLocation>::value, "");
   static_assert(std::is_same<typename X::TlvType::value_type, uint64_t>::value, "");
   static_assert(std::is_same<typename X::IsRepeatable::value_type, bool>::value, "");
-  NDN_CXX_ASSERT_DEFAULT_CONSTRUCTIBLE(typename X::ValueType);
-  BOOST_CONCEPT_ASSERT((boost::CopyConstructible<typename X::ValueType>));
+  static_assert(std::is_default_constructible<typename X::ValueType>::value, "");
+  static_assert(std::is_copy_constructible<typename X::ValueType>::value, "");
   BOOST_CONCEPT_USAGE(Field)
   {
     Block wire;
diff --git a/ndn-cxx/name-component.cpp b/ndn-cxx/name-component.cpp
index 3ed4c8e..36460b0 100644
--- a/ndn-cxx/name-component.cpp
+++ b/ndn-cxx/name-component.cpp
@@ -474,8 +474,7 @@
 {
   return type() == other.type() &&
          value_size() == other.value_size() &&
-         (empty() || // needed with Apple clang < 9.0.0 due to libc++ bug
-          std::equal(value_begin(), value_end(), other.value_begin()));
+         std::equal(value_begin(), value_end(), other.value_begin());
 }
 
 int
diff --git a/ndn-cxx/util/concepts.hpp b/ndn-cxx/util/concepts.hpp
index 5509ed3..90269ec 100644
--- a/ndn-cxx/util/concepts.hpp
+++ b/ndn-cxx/util/concepts.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018 Regents of the University of California,
+ * Copyright (c) 2014-2020 Regents of the University of California,
  *                         Arizona Board of Regents,
  *                         Colorado State University,
  *                         University Pierre & Marie Curie, Sorbonne University,
@@ -124,14 +124,12 @@
 {
 };
 
-// NDN_CXX_ASSERT_DEFAULT_CONSTRUCTIBLE and NDN_CXX_ASSERT_FORWARD_ITERATOR
-// originally written as part of NFD codebase
+// NDN_CXX_ASSERT_FORWARD_ITERATOR originally written as part of the NFD codebase
 
 namespace detail {
 
 // As of Boost 1.61.0, the internal implementation of BOOST_CONCEPT_ASSERT does not allow
 // multiple assertions on the same line, so we have to combine multiple concepts together.
-
 template<typename T>
 class StlForwardIteratorConcept : public boost::ForwardIterator<T>
                                 , public boost::DefaultConstructible<T>
@@ -139,15 +137,7 @@
 };
 
 } // namespace detail
-
-// std::is_default_constructible is broken in gcc-4.8, see bug #3882
-/** \brief assert T is default constructible
- *  \sa http://en.cppreference.com/w/cpp/concept/DefaultConstructible
- */
-#define NDN_CXX_ASSERT_DEFAULT_CONSTRUCTIBLE(T) \
-  static_assert(std::is_default_constructible<T>::value, \
-                #T " must be default-constructible"); \
-  BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<T>))
+} // namespace ndn
 
 /** \brief assert T is a forward iterator
  *  \sa http://en.cppreference.com/w/cpp/concept/ForwardIterator
@@ -159,6 +149,4 @@
                 #T " must be default-constructible"); \
   BOOST_CONCEPT_ASSERT((::ndn::detail::StlForwardIteratorConcept<T>))
 
-} // namespace ndn
-
 #endif // NDN_UTIL_CONCEPTS_HPP