// bsla_unreachable.h                                                 -*-C++-*-
#ifndef INCLUDED_BSLA_UNREACHABLE
#define INCLUDED_BSLA_UNREACHABLE

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide a compiler-hint macro to indicate unreachable code.
//
//@MACROS:
//  BSLA_UNREACHABLE: indicate that a statement is intended to be not reached
//  BSLA_UNREACHABLE_IS_ACTIVE: 1 if 'BSLA_UNREACHABLE' is active, 0 otherwise
//
//@SEE_ALSO: bsla_annotations
//
//@DESCRIPTION: This component provides a preprocessor macro that hints to the
// compile that a statement in the code is intended to be unreachable.  Note
// that an instance of 'BSLA_UNREACHABLE' must be followed by a ';' and is a
// statement in its own right.
//
///Macro Reference
///---------------
//: 'BSLA_UNREACHABLE'
//:     This macro will, when used and followed by a semicolon, create a
//:     statement that emits no code, but that is indicated to be unreachable,
//:     causing compilers, where supported, to issue warnings if there is
//:     actually a way that the statement can be reached.  Note that the
//:     behavior is undefined if control actually reaches a 'BSLA_UNREACHABLE'
//:     statement.
//
//: 'BSLA_UNREACHABLE_IS_ACTIVE'
//:     The macro 'BSLA_UNREACHABLE_IS_ACTIVE' is defined to 0 if
//:     'BSLA_UNREACHABLE' expands to nothing and 1 otherwise.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Indicating That a Statement is Intended to be Unreachable
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// First, we define a function, 'directoriesInPath', that counts the number of
// directories in the 'PATH' environment variable.  If 'PATH' is not set, the
// program dumps core by calling 'BSLS_ASSERT_OPT':
//..
//  int directoriesInPath()
//  {
//      const char *path = ::getenv("PATH");
//      if (path) {
//          int ret = 1;
//          for (; *path; ++path) {
//              ret += ':' == *path;
//          }
//          return ret;                                               // RETURN
//      }
//
//      BSLS_ASSERT_OPT(false && "$PATH not set");
//  }
//..
// Then, we observe a compile error because the compiler expects the
// 'BSLA_ASSERT_OPT' to return and the function to run off the end and return
// 'void', while the function is declated to return 'int'.
//..
//  .../bsla_unreachable.t.cpp(141) : error C4715: 'directoriesInPath': not all
//  control paths return a value
//..
// Now, we put a 'BSLA_UNREACHABLE' statement after the 'BSLS_ASSERT_OPT',
// which tells the compiler that that point in the code is unreachable:
//..
//  int directoriesInPath()
//  {
//      const char *path = ::getenv("PATH");
//      if (path) {
//          int ret = 1;
//          for (; *path; ++path) {
//              ret += ':' == *path;
//          }
//          return ret;                                               // RETURN
//      }
//
//      BSLS_ASSERT_OPT(false && "$PATH not set");
//
//      BSLA_UNREACHABLE;
//  }
//..
// Finally, we observe that the compiler error is silenced and the build is
// successful.

#include <bsls_platform.h>

#if defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)
    #define BSLA_UNREACHABLE __builtin_unreachable()

    #define BSLA_UNREACHABLE_IS_ACTIVE 1
#elif defined(BSLS_PLATFORM_CMP_MSVC)
    #define BSLA_UNREACHABLE __assume(false)

    #define BSLA_UNREACHABLE_IS_ACTIVE 1
#else
    #define BSLA_UNREACHABLE

    #define BSLA_UNREACHABLE_IS_ACTIVE 0
#endif

#endif

// ----------------------------------------------------------------------------
// Copyright 2019 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------