net+util: fix build with gcc-7

Introduce an NDN_CXX_FALLTHROUGH macro to simplify
annotating switch cases that fall through.

Update code-style to recommend using NDN_CXX_FALLTHROUGH.

Change-Id: I80e4ff8d16a09f6ec9343f0480bc57ae0fcd1be4
diff --git a/docs/code-style.rst b/docs/code-style.rst
index 5da9a60..354038e 100644
--- a/docs/code-style.rst
+++ b/docs/code-style.rst
@@ -211,7 +211,7 @@
         switch (condition) {
           case ABC:        // 2 space indent
             statements;    // 4 space indent
-            // Fallthrough
+            NDN_CXX_FALLTHROUGH;
 
           case DEF:
             statements;
@@ -242,7 +242,7 @@
           // Correct style
           case A1: {
             statements;
-            // Fallthrough
+            NDN_CXX_FALLTHROUGH;
           }
 
           // Incorrect style: braces should cover the entire case block
@@ -263,7 +263,7 @@
         switch (condition) {
         case ABC:        // no indent
           statements;    // 2 space indent
-          // Fallthrough
+          NDN_CXX_FALLTHROUGH;
 
         case DEF:
           statements;
@@ -274,9 +274,11 @@
           break;
         }
 
-    The explicit ``Fallthrough`` comment should be included whenever there is a case
-    statement without a break statement.  Leaving the break out is a common error, and it
-    must be made clear that it is intentional when it is not there.
+    The ``NDN_CXX_FALLTHROUGH;`` annotation must be included whenever there is
+    a case without a break statement. Leaving the break out is a common error,
+    and it must be made clear that it is intentional when it is not there.
+    Moreover, modern compilers will warn when a case that falls through is not
+    explicitly annotated.
 
 1.11. A ``try-catch`` statement should have the following form:
 
diff --git a/src/net/address-converter.cpp b/src/net/address-converter.cpp
index b6f2de2..d84f757 100644
--- a/src/net/address-converter.cpp
+++ b/src/net/address-converter.cpp
@@ -89,7 +89,7 @@
     if (!ec && addr.is_v6() && addr.to_v6().is_link_local()) {
       return {addr, parseResult[1]};
     }
-    // Fallthrough, if the presence of % is invalid set ec to invalid_argument
+    NDN_CXX_FALLTHROUGH;
   default:
     ec = boost::asio::error::invalid_argument;
     return {};
diff --git a/src/util/backports-optional.hpp b/src/util/backports-optional.hpp
index 29862b1..8f1f498 100644
--- a/src/util/backports-optional.hpp
+++ b/src/util/backports-optional.hpp
@@ -42,17 +42,15 @@
 #ifndef NDN_UTIL_BACKPORTS_OPTIONAL_HPP
 #define NDN_UTIL_BACKPORTS_OPTIONAL_HPP
 
-#include "../common.hpp"
+#include "backports.hpp"
 
-#ifdef __has_include
-#  if (__cplusplus > 201402L) && __has_include(<optional>)
-#    include <optional>
-#    define NDN_CXX_HAVE_STD_OPTIONAL
-#  elif (__cplusplus > 201103L) && __has_include(<experimental/optional>)
-#    include <experimental/optional>
-#    if __cpp_lib_experimental_optional >= 201411
-#      define NDN_CXX_HAVE_EXPERIMENTAL_OPTIONAL
-#    endif
+#if (__cplusplus > 201402L) && NDN_CXX_HAS_INCLUDE(<optional>)
+#  include <optional>
+#  define NDN_CXX_HAVE_STD_OPTIONAL
+#elif (__cplusplus > 201103L) && NDN_CXX_HAS_INCLUDE(<experimental/optional>)
+#  include <experimental/optional>
+#  if __cpp_lib_experimental_optional >= 201411
+#    define NDN_CXX_HAVE_EXPERIMENTAL_OPTIONAL
 #  endif
 #endif
 
diff --git a/src/util/backports-ostream-joiner.hpp b/src/util/backports-ostream-joiner.hpp
index 24a161c..75d53dd 100644
--- a/src/util/backports-ostream-joiner.hpp
+++ b/src/util/backports-ostream-joiner.hpp
@@ -27,16 +27,12 @@
 #ifndef NDN_UTIL_BACKPORTS_OSTREAM_JOINER_HPP
 #define NDN_UTIL_BACKPORTS_OSTREAM_JOINER_HPP
 
-#include "../common.hpp"
+#include "backports.hpp"
 
-#if __cplusplus >= 201402L
-#  ifdef __has_include
-#    if __has_include(<experimental/iterator>)
-#      include <experimental/iterator>
-#      if __cpp_lib_experimental_ostream_joiner >= 201411
-#        define NDN_CXX_HAVE_EXPERIMENTAL_OSTREAM_JOINER
-#      endif
-#    endif
+#if (__cplusplus >= 201402L) && NDN_CXX_HAS_INCLUDE(<experimental/iterator>)
+#  include <experimental/iterator>
+#  if __cpp_lib_experimental_ostream_joiner >= 201411
+#    define NDN_CXX_HAVE_EXPERIMENTAL_OSTREAM_JOINER
 #  endif
 #endif
 
diff --git a/src/util/backports.hpp b/src/util/backports.hpp
index 1d0a92a..df1d775 100644
--- a/src/util/backports.hpp
+++ b/src/util/backports.hpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2015-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -28,6 +28,30 @@
 #include <boost/lexical_cast.hpp>
 #endif
 
+#ifdef __has_cpp_attribute
+#  define NDN_CXX_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+#  define NDN_CXX_HAS_CPP_ATTRIBUTE(x) 0
+#endif
+
+#ifdef __has_include
+#  define NDN_CXX_HAS_INCLUDE(x) __has_include(x)
+#else
+#  define NDN_CXX_HAS_INCLUDE(x) 0
+#endif
+
+#if NDN_CXX_HAS_CPP_ATTRIBUTE(fallthrough)
+#  define NDN_CXX_FALLTHROUGH [[fallthrough]]
+#elif NDN_CXX_HAS_CPP_ATTRIBUTE(clang::fallthrough)
+#  define NDN_CXX_FALLTHROUGH [[clang::fallthrough]]
+#elif NDN_CXX_HAS_CPP_ATTRIBUTE(gnu::fallthrough)
+#  define NDN_CXX_FALLTHROUGH [[gnu::fallthrough]]
+#elif defined(__GNUC__) && (__GNUC__ >= 7)
+#  define NDN_CXX_FALLTHROUGH __attribute__((fallthrough))
+#else
+#  define NDN_CXX_FALLTHROUGH ((void)0)
+#endif
+
 namespace ndn {
 
 #if __cpp_lib_make_unique >= 201304