// bsla_deprecated.h                                                  -*-C++-*-
#ifndef INCLUDED_BSLA_DEPRECATED
#define INCLUDED_BSLA_DEPRECATED

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

//@PURPOSE: Provide compiler-hint macros to indicate deprecated entities.
//
//@MACROS:
//  BSLA_DEPRECATED:           warn if annotated (deprecated) entity is used
//  BSLA_DEPRECATED_MESSAGE:   warn with message if annotated entity is used
//  BSLA_DEPRECATED_IS_ACTIVE: defined if both macros are active
//
//@SEE_ALSO: bsla_annotations
//
//@DESCRIPTION: This component provides preprocessor macros that hint to the
// compiler that a function, variable, type, `typedef`, `struct` member, `enum`
// type, or template specialization is deprecated.  This is useful, for
// example, when identifying functions that are expected to be removed in a
// future version of a library.
//
///Macro Reference
///---------------
//: `BSLA_DEPRECATED`:
//:    This annotation will, when used, cause a compile-time warning if the
//:    so-annotated function, variable, type, `typedef`, `struct` member,
//:    `enum` type, or template specialization is used anywhere within the
//:    source file.  The warning includes the location of the declaration of
//:    the deprecated entity to enable users to find further information about
//:    the deprecation, or what they should use instead.
//:
//: `BSLA_DEPRECATED_MESSAGE(QUOTED_MESSAGE)`:
//:    This annotation will, when used, cause a compile-time warning if the
//:    so-annotated function, variable, type, `typedef`, `struct` member,
//:    `enum` type, or template specialization is used anywhere within the
//:    source file.  The compiler warning will contain the contents of the
//:    specified `QUOTED_MESSAGE`, which must be a double-quoted string.  The
//:    warning includes the location of the declaration of the deprecated
//:    entity to enable users to find further information about the
//:    deprecation, and what they should use instead.  Note that on some
//:    compilers `QUOTED_MESSAGE` is ignored.
//:
//: `BSLA_DEPRECATED_IS_ACTIVE`:
//:   The macro `BSLA_DEPRECATED_IS_ACTIVE` is defined if `BSLA_DEPRECATED` and
//:   `BSLA_DEPRECATED_MESSAGE` are both active and have the desired effect;
//:   otherwise, `BSLA_DEPRECATED_IS_ACTIVE` is not defined and both other
//:   macros expand to nothing.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Various Deprecations
///- - - - - - - - - - - - - - - -
// First, we define a deprecated type `UsageType`:
// ```
// struct BSLA_DEPRECATED UsageType {
//     int d_int;
// };
// ```
// Then, we define a function `usageFunc` that is deprecated:
// ```
// BSLA_DEPRECATED
// void usageFunc();
// void usageFunc()
// {
//     printf("Don't call me.\n");
// }
// ```
// Next, we define a variable `usageVar` that is deprecated:
// ```
// BSLA_DEPRECATED extern int usageVar;
// int usageVar = 5;
// ```
// Then, we define a typedef `UsageTypedef` that is deprecated:
// ```
// BSLA_DEPRECATED typedef int UsageTypedef;
// ```
// Next, we define a `struct` with a member `d_y` that is deprecated:
// ```
// struct UsageStruct {
//     double                 d_x;
//     BSLA_DEPRECATED double d_y;
// };
// ```
// Then, we define an `enum` `UsageEnum` that is deprecated:
// ```
// enum BSLA_DEPRECATED UsageEnum { e_FALSE, e_TRUE };
// ```
// Next, we define a template this is only deprecated in the case where it is
// specialized with the `int` type as a template parameter:
// ```
// template <class TYPE>
// TYPE usageAbs(TYPE x)
// {
//     return x < 0 ? -x : x;
// }
//
// template <>
// BSLA_DEPRECATED_MESSAGE("'int' specialization not allowed")
// int usageAbs<int>(int x)
// {
//     int ret = x < 0 ? -x : x;
//     return ret < 0 ? ~ret : ret;
// }
// ```
// Then, as long as we don't use them, no warnings will be issued.
//
// Next, we use `UsageType`:
// ```
// UsageType ut;
// ut.d_int = 5;
// (void) ut.d_int;
// ```
// which results in the following warnings:
// ```
// .../bsla_deprecated.t.cpp:287:5: warning: 'UsageType' is deprecated
// [-Wdeprecated-declarations]
//     UsageType ut;
//     ^
// .../bsla/bsla_deprecated.t.cpp:113:7: note: 'UsageType' has been explicitly
//  marked deprecated here
//     } BSLA_DEPRECATED;
//       ^
// ```
// Then, we call `usageFunc`:
// ```
// usageFunc();
// ```
// which results in the following warnings:
// ```
// .../bsla_deprecated.t.cpp:309:5: warning: 'usageFunc' is deprecated
// [-Wdeprecated-declarations]
//     usageFunc();
//     ^
// .../bsla_deprecated.t.cpp:117:22: note: 'usageFunc' has been explicitly
// marked deprecated here
//     void usageFunc() BSLA_DEPRECATED;
//                      ^
// ```
// Next, we access `usageVar`:
// ```
// printf("%d\n", usageVar);
// ```
// which results in the following warnings:
// ```
// .../bsla_deprecated.t.cpp:326:20: warning: 'usageVar' is deprecated
// [-Wdeprecated-declarations]
//     printf("%d\n", usageVar);
//                    ^
// .../bsla_deprecated.t.cpp:134:25: note: 'usageVar' has been explicitly
// marked deprecated here
//     extern int usageVar BSLA_DEPRECATED;
//                         ^
// .../bsla_deprecated.h:119:32: note: expanded from macro 'BSLA_DEPRECATED'
// #     define BSLA_DEPRECATED [[deprecated]]
// ```
// Then, we use `UsageTypedef`:
// ```
// UsageTypedef jjj = 32;
// (void) jjj;
// ```
// which results in the following warnings:
// ```
// .../bsla_deprecated.t.cpp:379:5: warning: 'UsageTypedef' is deprecated
// [-Wdeprecated-declarations]
//     UsageTypedef jjj = 32;
//     ^
// .../bsla_deprecated.t.cpp:140:5: note: 'UsageTypedef' has been explicitly
// marked deprecated here
//     BSLA_DEPRECATED typedef int UsageTypedef;
//     ^
// ```
// Next, we access the deprecated member of `UsageStruct`:
// ```
// UsageStruct us;
// ::memset(&us, 0, sizeof(us));
// assert(0 == us.d_x);    // no warning
// assert(0 == us.d_y);    // 'd_y' is deprecated -- issues warning.
// ```
// which results in the following warnings:
// ```
// .../bsla_deprecated.t.cpp:387:20: warning: 'd_y' is deprecated
// [-Wdeprecated-declarations]
//     assert(0 == us.d_y);    // 'd_y' is deprecated -- issues warning.
//                    ^
// .../bsla_deprecated.t.cpp:146:9: note: 'd_y' has been explicitly marked
// deprecated here
//         BSLA_DEPRECATED double d_y;
//         ^
// ```
// Now, we use the deprecated `UsageEnum`:
// ```
// UsageEnum ue;
// ue = e_TRUE;
// (void) ue;
// ```
// which results in the following warnings:
// ```
// .../bsla_deprecated.t.cpp:411:15: warning: 'UsageEnum' is deprecated
// [-Wdeprecated-declarations]
//      UsageEnum ue;
//                ^
// .../bsla_deprecated.t.cpp:152:26: note: declared here
//      enum BSLA_DEPRECATED UsageEnum { e_FALSE, e_TRUE };
//                           ^
// ```
// Finally, we access the deprecated specialization of `usageAbs`:
// ```
// assert(2.0 == usageAbs(-2.0));            // no warning, 'usageAbs<double>'
//                                           // not deprecated
// assert(INT_MAX == usageAbs(INT_MIN));     // warning, 'usageAbs<int>' is
//                                           // deprecated
// ```
// which results in the following warnings:
// ```
// .../bsla_deprecated.t.cpp:441:39: warning: 'TYPE usageAbs(TYPE) [with TYPE
// = int]' is deprecated: 'int' specialization not allowed
// [-Wdeprecated-declarations]
//      assert(INT_MAX == usageAbs(INT_MIN));     // warning, 'usageAbs<int>'
//                                        ^
// .../bsla_deprecated.t.cpp:168:9: note: declared here
//      int usageAbs<int>(int x)
//          ^~~~~~~~~~~~~
// ```

#include <bsls_platform.h>

                       // =============================
                       // Checks for Pre-Defined macros
                       // =============================

#if defined(BSLA_DEPRECATED)
#error BSLA_DEPRECATED is already defined!
#endif

#if defined(BSLA_DEPRECATED_MESSAGE)
#error BSLA_DEPRECATED_MESSAGE is already defined!
#endif

#if defined(BSLA_DEPRECATED_IS_ACTIVE)
#error BSLA_DEPRECATED_IS_ACTIVE is already defined!
#endif

                       // =========================
                       // Set macros as appropriate
                       // =========================

#if (defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)) &&   \
                                                   defined(__has_cpp_attribute)
# if __has_attribute(deprecated)
#   if 201402L <= __cplusplus ||                                              \
                     (defined(BSLS_PLATFORM_CMP_GNU) && 201103L <= __cplusplus)
#     define BSLA_DEPRECATED                  [[ deprecated ]]
#     define BSLA_DEPRECATED_MESSAGE(message) [[ deprecated(message) ]]
#   else
#     define BSLA_DEPRECATED                  __attribute__((__deprecated__))
#     define BSLA_DEPRECATED_MESSAGE(message) __attribute__((__deprecated__))
#   endif

#   define BSLA_DEPRECATED_IS_ACTIVE 1
# endif
#else
# define BSLA_DEPRECATED
# define BSLA_DEPRECATED_MESSAGE(message)
#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 ----------------------------------
