// bsls_deprecate.h -*-C++-*- #ifndef INCLUDED_BSLS_DEPRECATE #define INCLUDED_BSLS_DEPRECATE //@PURPOSE: Provide machinery to deprecate interfaces on a per-version basis. // //@MACROS: // BSLS_DEPRECATE: tag an interface as deprecated // BSLS_DEPRECATE_IS_ACTIVE: conditionally activate deprecation by UOR version // BSLS_DEPRECATE_MAKE_VER: render UOR version for deprecation threshold // //@DESCRIPTION: This component defines a suite of macros to control (on a // per-version, per-UOR basis) the deprecation of functions, user-defined // types, and 'typedef's, and the conditional compilation of enumerators and // preprocessor macros. The 'bsls_deprecate' facility operates by triggering // compiler warnings when types or interfaces are used that have been tagged // with deprecation macros defined by this component. Unlike previous // deprecation facilities based exclusively on the use of '#ifndef' with global // macros (such as 'BDE_OMIT_DEPRECATED' and 'BDE_OMIT_INTERNAL_DEPRECATED'), // supported use of the 'bsls_deprecate' facility does *not* affect a UOR's // ABI. It is therefore safe to link applications based on libraries built // with different deprecation policies. // ///Overview: Common Uses ///--------------------- // ///Applying a Deprecation Tag to an Interface /// - - - - - - - - - - - - - - - - - - - - - // UOR owners who wish to mark an interface as deprecated can do so by tagging // the declaration of that interface with the 'BSLS_DEPRECATE' macro, wrapped // in a '#if' block to apply 'BSLS_DEPRECATE' only when // 'BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)' evaluates to true for a given version // 'M.N' of the specified 'UOR': //.. // #if BSLS_DEPRECATE_IS_ACTIVE(BDE, 3, 2) // BSLS_DEPRECATE // #endif // int foo(const char *bar); // // !DEPRECATED!: Use 'newFoo' instead. //.. // The above application of 'BSLS_DEPRECATE_IS_ACTIVE' indicates that 'foo' is // deprecated starting with 'bde' version 3.2. Once the deprecation threshold // for 'bde' advances to version 3.2, code calling 'foo' will generate a // deprecation warning with compilers that support deprecation attributes. // (See {Version Control Macros for Library Authors} for information on // defining a deprecation threshold for a UOR.) Note that in the absence of an // explicit deprecation threshold ('BDE_VERSION_DEPRECATION_THRESHOLD', in this // case), code calling 'foo' would begin generating deprecation warnings in the // very next minor or major release of 'bde' (3.3 or 4.0, whichever applies). // // If an interface has several entities being deprecated at the same time, // clients can define a new deprecation macro within that header to avoid // repeated use of 'BSLS_DEPRECATE_IS_ACTIVE': //.. // // bdexyz_component.h -*-C++-*- // // #if BSLS_DEPRECATE_IS_ACTIVE(BDE, 3, 2) // #define BDEXYZ_COMPONENT_DEPRECATED_3_2 BSLS_DEPRECATE // #else // #define BDEXYZ_COMPONENT_DEPRECATED_3_2 // #endif // // // ... // // BDEXYZ_COMPONENT_DEPRECATED_3_2 // int foo(); // // BDEXYZ_COMPONENT_DEPRECATED_3_2 // int bar(); // // // ... // // #undef BDEXYZ_COMPONENT_DEPRECATED_3_2 //.. // ///Keeping Your Code Free of Calls to Deprecated Interfaces /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - // When an interface is tagged with 'BSLS_DEPRECATE' as shown above, the // deprecation is initially _not_ _enforced_ by default. That is, a normal // build of code calling the deprecated interface will not emit a deprecation // warning. // // Downstream developers who wish to make sure that their code uses no // deprecated interfaces can do so by defining the symbol // 'BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY' in their build system. //.. // $ CXXFLAGS=-DBB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY make my_application // # A compiler that supports 'BSLS_DEPRECATE' will emit a warning if any // # deprecated interfaces are used in 'my_application', even if those // # deprecations are scheduled to take effect in a future release. //.. // *NEVER* define 'BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY' in a // *PRODUCTION* *BUILD* *CONFIGURATION*. If you do so, all libraries that you // depend on will be prevented from deprecating more code in future versions. // ///Preventing New Uses of Already-Deprecated Interfaces /// - - - - - - - - - - - - - - - - - - - - - - - - - - // At some point after an interface has been tagged with 'BSLS_DEPRECATE', the // library owner can make new uses of that interface generate warnings by // defining a deprecation threshold for the UOR that contains the deprecated // interface (or by adjusting the deprecation threshold for the UOR if it // already exists). Defining a deprecation threshold _enforces_ deprecations // made in all versions up to and including the threshold. If the version // number of the deprecation threshold is greater than or equal to the version // number specified in the 'BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)' macro, then // the 'BSLS_DEPRECATE' macro will be enabled and generate a warning. // // This is the recommended way to define a deprecation threshold (see {Version // Control Macros for Library Authors}): //.. // // bdescm_versiontag.h // // // ... // // #define BDE_VERSION_DEPRECATION_THRESHOLD BSLS_DEPRECATE_MAKE_VER(3, 2) // // // All 'bde' deprecations tied to release 3.2 or earlier will trigger // // compiler warnings. //.. // ///Background ///---------- // Prior to the availability of this component, when a developer wanted to // deprecate an API they might either apply an attribute to the API that would // generate a warning, or they would use '#ifdef' to remove deprecated code // when it is built with appropriate options. These solutions have a practical // shortcoming in a production environment like Bloomberg's, where code changes // in lower-level libraries cannot be checked in if they break the build of // (higher-level) client libraries. In such a system, well-meaning clients // might build their libraries using '-Werror' (to turn compilation warnings // into errors) or with appropriate '#ifdef's to ensure their code does not use // deprecated APIs, but in so doing they hinder the introduction of any new // deprecations. In addition, the use of '#ifdef' results in ABI compatibility // issues, as some clients may build with deprecated code removed, and others // may not. // // This deprecation facility is based around two concepts that attempt to // address these shortcomings: // //: 1 This facility is designed to provide ABI compatibility. //: 'BSLS_DEPRECATE_*' macros are used to trigger *compilation* *warnings* //: on platforms that support deprecation attributes, instead of *removing* //: *code* from the codebase. //: //: 2 Typically, use of this facility will not immediately generate a warning //: in client code. The use of the 'BSLS_DEPRECATE' macro is generally //: guarded by a version check using 'BSLS_DEPRECATE_IS_ACTIVE'. In an //: environment where compiler warnings are considered to be build failures, //: it is possible (and encouraged) to tag a C++ entity with a deprecation //: macro in one release cycle, and not have that deprecation affect any //: clients by default until a later release cycle. During the intervening //: period, clients have an opportunity to proactively check their code for //: uses of newly-deprecated code. // // Notice that the cost for maintaining ABI compatibility is that clients // cannot check whether they are using deprecated interfaces unless they build // their software on certain platforms with warnings activated. For this // facility to be effective across an enterprise, it is required that such // warning-enabled builds be part of the standard process for checking in code // in the enterprise. // ///Mechanics ///--------- // This component stipulates two sets of macros. One set of deprecation // macros, defined in this component, are used to identify a C++ entity as // being deprecated in a given version of a given UOR. A second set of control // macros, defined by clients of this component, dictates which deprecation // macros are enforced at any point in the code during compilation. // ///Deprecation Macros /// - - - - - - - - - //: 'BSLS_DEPRECATE': //: Expands to a particular deprecation attribute with compilers that have //: such support; otherwise, 'BSLS_DEPRECATE' expands to nothing. //: 'BSLS_DEPRECATE' can be applied to 'class' or 'struct' definitions, //: function declarations, and 'typedef's. //: //: 'BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)': //: Expands to 1 if deprecations are enforced for the specified version 'M.N' //: of the specified 'UOR', and to 0 otherwise. // // These two macros are intended to be placed together in a preprocessor '#if' // block in front of a function, type, or 'typedef' declaration, with // 'BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)' controlling whether or not // 'BSLS_DEPRECATE' is applied to the declaration. The exact placement of the // block should match the requirements of the C++14 '[[deprecated]]' attribute. // // Examples: //.. // class // #if BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2) // BSLS_DEPRECATE // #endif // SomeType { // // ... // }; // // struct SomeUtil { // #if BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2) // BSLS_DEPRECATE // #endif // static int someFunction(); // }; // // #if BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2) // BSLS_DEPRECATE // #endif // typedef SupportedType DeprecatedType; //.. // At present, the underlying compiler intrinsics represented by // 'BSLS_DEPRECATE' cannot be applied uniformly to some C++ constructs, most // notably variables, enumerators, and preprocessor macros. Fortunately, these // constructs can often be removed from a library without otherwise affecting // ABI, so '!BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)' can be used with a '#if' // directive to entirely remove blocks of code containing those C++ constructs. // // Example: //.. // #if !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2) // // #define MY_DEPRECATED_MACRO // // Macro definitions can be removed with 'BSLS_DEPRECATE_IS_ACTIVE'. // // #endif // !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2) // // namespace grppkg { // // #if !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 3) // // SomeType myDeprecatedGlobalVariable; // // Variables at 'namespace' or global scope can be removed with // // 'BSLS_DEPRECATE_IS_ACTIVE'. // // #endif // !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 3) // // // ... // // } // close namespace 'grppkg' //.. // Note the use of the '!' operator: deprecated code is compiled only if // deprecations are *not* enforced for the specified UOR version. // // Particular care must be taken to ensure that deprecating one or more // enumerators does not (inadvertently) change the values of other enumerators // in the same 'enum': //.. // enum MyEnum { // e_FIRST, // e_SECOND, // e_THIRD, // #if !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2) // // These legacy enumerators can be deprecated because their removal // // does not affect the values of any other enumerators. // // FIRST = e_FIRST, // SECOND = e_SECOND, // THIRD = e_THIRD // #endif // }; //.. // ///Version Control Macros for Library Authors /// - - - - - - - - - - - - - - - - - - - - - // A UOR-specific deprecation threshold can be (and typically *should* be) // specified by the authors of a UOR to govern which of their deprecations are // active by default: //: '<UOR>_VERSION_DEPRECATION_THRESHOLD': //: This macro should be defined in '<uor>scm_versiontag.h' alongside //: '<UOR>_VERSION_MAJOR' and '<UOR>_VERSION_MINOR' to indicate the greatest //: version of the unit of release 'UOR' for which deprecations are enforced //: by default. // // Example: //.. // // abcscm_versiontag.h // // #define ABC_VERSION_MAJOR 1 // #define ABC_VERSION_MINOR 4 // // #define ABC_VERSION_DEPRECATION_THRESHOLD BSLS_DEPRECATE_MAKE_VER(1, 2) //.. // In this example, 'BSLS_DEPRECATE_IS_ACTIVE(ABC, M, N)' will expand to 1 for // all versions 'M.N' of 'ABC' up to and including version 1.2. For 'M.N' // later than 1.2 (e.g., 1.3 or 2.0), 'BSLS_DEPRECATE_IS_ACTIVE(ABC, M, N)' // will expand to 1 only if the 'BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY' // macro is defined by the user (see {Build Control Macros for Clients}). // // Note that if a deprecation threshold is *not* explicitly defined for a UOR // that defines '<UOR>_VERSION_MAJOR' and '<UOR>_VERSION_MINOR', then // 'BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)' will expand to 1 once the version // indicated by '<UOR>_VERSION_MAJOR' and '<UOR>_VERSION_MINOR' becomes greater // than 'M.N'. For example, 'BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 4)' will expand // to 1 in version 1.5 of 'ABC' (or 2.0 if there is no release 1.5) if // 'ABC_VERSION_DEPRECATION_THRESHOLD' is not defined. For this reason, it is // highly recommended that UOR authors explicitly define a deprecation // threshold to avoid unexpected build failures when a new release is issued, // especially in environments where warnings are considered fatal. // // A second UOR-specific macro is available to the authors of a UOR that must, // for whatever reason, continue to use interfaces that are deprecated in their // own library: //: 'BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<UOR>': //: This macro prevents 'bsls_deprecate' from enforcing deprecations for all //: versions of 'UOR'. This macro must be defined in each '.cpp' file of //: 'UOR' that either uses a deprecated interface from the *same* UOR that //: has reached the deprecation threshold for 'UOR', or includes a header //: file of 'UOR' that uses such an interface in inline code. This macro //: must be defined before the first '#include' of a header from 'UOR'. // // Example: //.. // // abcxyz_somecomponent.cpp // // #define BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_ABC // // #include <abcxyz_somecomponent.h> // // // ... //.. // ///Build Control Macros for Clients /// - - - - - - - - - - - - - - - - // The following two macros are intended for client use during builds, either // to *enable* *all* deprecations or to *suppress* *selected* deprecations: //: 'BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY': //: This macro should be defined as a '-D' parameter during test builds of //: components that are intended to be deprecation-clean. When this macro is //: defined, deprecations will be enforced for all versions of all UORs, //: except as overridden by 'BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<UOR>' //: (see {Version Control Macros for Library Authors} or //: 'BB_SILENCE_DEPRECATIONS_<UOR>_<M>_<N>' (see below). This macro must //: *never* appear in source code, and must *never* be defined for any //: production or check-in build configuration. //: //: 'BB_SILENCE_DEPRECATIONS_<UOR>_<M>_<N>': //: This macro should be defined by clients of 'UOR' who still need to use an //: interface that was deprecated in version 'M.N' after the deprecation //: threshold for 'UOR' has reached (or exceeded) 'M.N'. This macro should //: be defined *before* the first '#include' of a header from 'UOR'. This //: macro must *never* be defined in a header file. // // Example: //.. // // grppkg_fooutil.cpp // // #define BB_SILENCE_DEPRECATIONS_ABC_1_2 // // 'BB_SILENCE_DEPRECATIONS_ABC_1_2' must be defined before the // // component's own '#include' directive in case 'grppkg_fooutil.h' // // includes headers from 'abc' (directly or transitively). // // #include <grppkg_fooutil.h> // // // Interfaces from 'abcxyz_someutil' deprecated in version 1.2 of 'abc' // // will not trigger compiler warnings when used in 'grppkg_fooutil.cpp'. // // #include <abcxyz_someutil.h> // ... // // namespace grppkg { // // void FooUtil::foo() // { // int result = abcxyz::SomeUtil::someFunction(); // // ... // } // // } // close package namespace //.. // ///Supporting Compilers ///-------------------- // 'BSLS_DEPRECATE' will produce a warning with the following compilers: //: o gcc 4.3+ //: o clang 3.4+ //: o Xcode 4.4+ //: o Microsoft Visual Studio 2010 or later // // Additionally, 'BSLS_DEPRECATE' will produce a warning with any compiler that // provides the C++14 'deprecated' attribute. // ///Suggested Process for Deprecating Code (the Deprecation/Deletion Tango) ///----------------------------------------------------------------------- // Deprecation is a negotiation process between code authors and code consumers // to allow old code to be removed from the codebase. This component supports // a deprecation model where code moves through four steps from being fully // supported, to optionally deprecated, to fully deprecated, and finally to // being deleted. At each step, responsibility for moving the process forward // is passed back and forth between library authors and library users. // // When the owners of a library want to deprecate an interface, they start by // adding appropriate deprecation macros, specifying their UOR and the version // of their next release. For example, suppose package group 'abc' is // currently at version 1.1. If the owners of 'abc' want to deprecate a // function 'abcxyz::SomeUtil::someFunction', they could add the deprecation // macros 'BSLS_DEPRECATE' and 'BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2)' in front // of the declaration of 'someFunction': //.. // // abcxyz_someutil.h // // ... // // struct SomeUtil { // // ... // // #if BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2) // BSLS_DEPRECATE // #endif // static int someFunction(); // // DEPRECATED: use 'abcdef::OtherUtil::otherFunction' instead. // // ... // // }; //.. // At this point deprecations are not enforced by default for version 1.2 of // 'abc', so the deprecation macro alone will not have any affect on clients. // A client building their code normally will trigger no compiler warnings due // to this new deprecation: //.. // $ make grppkg_fooutil // ... dependencies: abc version 1.2 ... // ... no warnings ... //.. // If the owners of a client library or application want to check that their // code uses no deprecated interfaces, they can define the // 'BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY' flag in their *test* build // process. A compiler that supports deprecation attributes will then trigger // compiler warnings: //.. // $ CXXFLAGS=-DBB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY make grppkg_fooutil // ... dependencies: abc version 1.2 ... // grppkg_fooutil.cpp:43: warning: function 'abcxyz::SomeUtil::someFunction' // is explicitly deprecated. //.. // !WARNING!: Clients at Bloomberg *must* *not* define // 'BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY' in a production build. This // flag should be used for development builds only. // // Now the owners have the opportunity to fix their code by removing the // dependency on 'abcxyz::SomeUtil::someFunction'. // // At some point in the future, possibly on release of 'abc' version 1.3, the // owners of 'abc' will make deprecations enforced by default for version 1.2 // of 'abc', by setting the deprecation threshold for 'abc' in their version // control headers: //.. // // abcscm_versiontag.h // // #define ABC_VERSION_MAJOR 1 // #define ABC_VERSION_MINOR 3 // // ... // // #define ABC_VERSION_DEPRECATION_THRESHOLD BSLS_DEPRECATE_MAKE_VER(1, 2) //.. // If the owners of 'grp' have cleaned up their code, normal builds will // trigger no compiler warnings. However, any new development by any clients // will trigger warnings if they add a new use of // 'abcxyz::SomeUtil::someFunction': //.. // $ make foobar_bazutil // ... dependencies: abc version 1.3 ... // foobar_bazutil.cpp:177: warning: function 'abcxyz::SomeUtil::someFunction' // is explicitly deprecated. //.. // But what if the owners of 'grp' will not, or for some reason cannot, clean // up their code in the near term? Moving the threshold for 'abc' to version // 1.2 will of course trigger warnings when the owners of 'grp' next try to // build 'grppkg_fooutil'. In a development context requiring that all // production builds remain warning-free, we would be at an impasse: either the // owners of 'grp' must clean up their code immediately, or the owners of 'abc' // will not be able to enforce deprecations by default for version 1.2. // // This impasse can be resolved by allowing the owners of 'grp' to locally // silence warnings caused by deprecations for version 1.2 of 'abc'. This is // done by adding a definition of 'BB_SILENCE_DEPRECATIONS_ABC_1_2' to any // '.cpp' files that use 'abcxyz::SomeUtil::someFunction': //.. // // grppkg_fooutil.cpp // #define BB_SILENCE_DEPRECATIONS_ABC_1_2 // // ... //.. // Now the entire codebase can build warning-free again. // // Managers can easily detect 'BB_SILENCE_DEPRECATIONS_<UOR>_<M>_<N>' macros in // the codebase, and put pressure on teams to remove such remnant uses of // deprecated code. When all remnant uses have been removed, then the // deprecated function can be deleted entirely: //.. // // abcxyz_someutil.h // // ... // // struct SomeUtil { // // ... // // // RIP: The function formerly known as 'someFunction'. // // ... // // }; //.. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Tagging a Function as Deprecated ///- - - - - - - - - - - - - - - - - - - - - - // When one piece of code has been superseded by another, we would like to get // users to adopt the new code and stop using the old code. Being able to // inform clients that they need to clean up existing uses of the old code, and // also to prevent *new* uses of that code, makes it easier to get to the point // where old code actually has zero uses and can be deleted. The deprecation // macros 'BSLS_DEPRECATE' and 'BSLS_DEPRECATE_IS_ACTIVE', and their associated // control macros, can be used to gradually reduce the number of uses of // deprecated code, so that it can be removed eventually. // // Suppose we own package group 'xxx' that is currently at version 7.6. One of // our components contains a function 'foo' that has been superseded by another // function 'bar'. //.. // int foo(int *coefficient, int n); // // Load into the specified 'coefficient' the (positive) Winkelbaum // // Coefficient of the specified 'n'. Return 0 on success, and a // // negative number if there is no coefficient corresponding to 'n'. // // Note that every integer divisible by the Winkelbaum Modulus (17) has // // a corresponding Winkelbaum Coefficient. // // // ... // // int bar(int n); // // Return the (positive) Winkelbaum Coefficient of the specified 'n'. // // The behavior is undefined unless 'n' is divisible by 17 (the // // Winkelbaum Modulus). //.. // First, we add a deprecation tag to the declaration of 'foo', showing that it // will be deprecated starting with version 7.7, and update the documentation // accordingly: //.. // #if BSLS_DEPRECATE_IS_ACTIVE(XXX, 7, 7) // BSLS_DEPRECATE // #endif // int foo(int *coefficient, int n); // // !DEPRECATED!: Use 'bar' instead. // // // // Load into the specified 'coefficient' the (positive) Winkelbaum // // Coefficient of the specified 'n'. Return 0 on success, and a // // negative number if there is no coefficient corresponding to 'n'. // // Note that every integer divisible by the Winkelbaum Modulus (17) has // // a corresponding Winkelbaum Coefficient. // // // ... // // int bar(int n); // // Return the (positive) Winkelbaum Coefficient of the specified 'n'. // // The behavior is undefined unless 'n' is divisible by 17 (the // // Winkelbaum Modulus). //.. // When we release version 7.7, the added deprecation tag will not immediately // affect any of the users of 'foo'. However if any of those users do a test // build of their code with '-DBB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY', they // will see a warning that 'foo' has been deprecated. // // Finally, when enough time has passed to allow all users of 'foo' to switch // over to using 'bar', probably on or after the release of 'xxx' version 7.8, // we can enforce the deprecation of 'foo' by moving the deprecation threshold // for 'xxx' to version 7.7, to indicate that all interfaces deprecated for // version 7.7 are disallowed by default: //.. // // xxxscm_versiontag.h // // #define XXX_VERSION_MAJOR 7 // #define XXX_VERSION_MINOR 8 // // // ... // // #define XXX_VERSION_DEPRECATION_THRESHOLD BSLS_DEPRECATE_MAKE_VER(7, 7) //.. // ============== // BSLS_DEPRECATE // ============== // First, try to determine if the C++14 'deprecated' attribute is supported, // using standard feature-detection facilities. Note that Sun CC breaks this // detection by defining a macro called '__has_cpp_attribute' that reports // compile-errors rather than returning a 0 literal when called with // 'deprecated'. #if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) // Check the Sun compiler macros directly, rather than rely on the BDE // platform-detection macros in 'bsls_platform', to allow deprecation of // features in that component in the future. This feature was last // tested with CC 12.5. #if defined(__has_cpp_attribute) # if __has_cpp_attribute(deprecated) # define BSLS_DEPRECATE [[deprecated]] # if defined(__clang__) && __cplusplus < 201402L // Clang issues a warning when the C++14 attribute is used before C++14, // where it is offered as an extension rather than a feature. # undef BSLS_DEPRECATE # endif # if defined(__GNUC__) && __cplusplus < 201103L // G++ passes the '__has_cpp_attribute(deprecated)' test, but still // produces an error when '[[deprecated]]' is used in non-C++11 mode. # undef BSLS_DEPRECATE # endif # endif #endif // Then, try to determine if a GCC-style deprecation attribute is supported, // using semi-standard feature-detection facilities. #ifndef BSLS_DEPRECATE # if defined(__has_attribute) # if __has_attribute(deprecated) # define BSLS_DEPRECATE __attribute__ ((deprecated)) # endif # endif #endif #endif // Sun-avoidance // Next, define non-standard attributes for platforms known to support them. #ifndef BSLS_DEPRECATE # if defined(__GNUC__) // All compilers in the GNUC interface family (g++ and clang) provide the // simple gcc extension attribute. # define BSLS_DEPRECATE __attribute__ ((deprecated)) # elif defined (_MSC_VER) // All versions of MSVC supported by BDE provide a 'deprecate' declaration // specifier. # define BSLS_DEPRECATE __declspec(deprecated) # endif #endif // Finally, record whether the current compiler supports some form of // deprecation attribute. #ifdef BSLS_DEPRECATE # define BSLS_DEPRECATE_COMPILER_SUPPORT 1 #else # define BSLS_DEPRECATE_COMPILER_SUPPORT 0 // Provide a fallback empty definition when the compiler does not support // deprecation attributes. # define BSLS_DEPRECATE #endif // ============================================================================ // INTERNAL MACHINERY // ============================================================================ // ================== // BSLS_DEPRECATE_CAT // ================== #define BSLS_DEPRECATE_CAT(X, Y) BSLS_DEPRECATE_CAT_A(X, Y) // Expand to the expansion of the specified 'X', joined to the expansion of // the specified 'Y'. #define BSLS_DEPRECATE_CAT_A(X, Y) BSLS_DEPRECATE_CAT_B(X, Y) #define BSLS_DEPRECATE_CAT_B(X, Y) X ## Y // Internal implementation machinery for 'BSLS_DEPRECATE_CAT'. // ======================== // BSLS_DEPRECATE_ISDEFINED // ======================== #define BSLS_DEPRECATE_ISDEFINED(...) BSLS_DEPRECATE_ISDEFINED_A(__VA_ARGS__) // Expand to an expression evaluating to 'true' in a preprocessor context // if the deprecation control macro symbol supplied as an argument has been // '#define'd as nil, 0, or 1, and expand to an expression evaluating to // 'false' otherwise. The behavior is undefined unless this macro is // evaluated with a single argument having the form of a deprecation // control macro symbol, and that symbol has either not been '#define'd at // all or has been '#define'd as nil, 0, or 1. #define BSLS_DEPRECATE_ISDEFINED_A(...) ((__VA_ARGS__ ## 1L) != 0) // Internal implementation machinery for 'BSLS_DEPRECATE_ISDEFINED'. // ======================== // BSLS_DEPRECATE_ISNONZERO // ======================== #define BSLS_DEPRECATE_ISNONZERO(...) BSLS_DEPRECATE_ISNONZERO_A(__VA_ARGS__) // Expand to an expression evaluating to 'true' in a preprocessor context // if the deprecation control macro symbol supplied as an argument has been // '#define'd as an expression that evaluates to a non-zero value, and // expand to an expression evaluating to 'false' otherwise. The behavior // is undefined unless this macro is evaluated with a single argument // having the form of a deprecation control macro symbol, and that symbol // has either not been '#define'd at all, or has been '#define'd as nil or // an arithmetic expression. #define BSLS_DEPRECATE_ISNONZERO_A(...) (__VA_ARGS__ + 1 != 1) // Internal implementation machinery for 'BSLS_DEPRECATE_ISNONZERO'. // ======================= // BSLS_DEPRECATE_MAKE_VER // ======================= #define BSLS_DEPRECATE_MAKE_VER(M, N) ((M) * 1000 + (N)) // Expand to an opaque sequence of symbols encoding a UOR version where // the specified 'M' is the major version number and the specified 'N' is // the minor version number. // ============================== // BSLS_DEPRECATE_ISPASTTHRESHOLD // ============================== #define BSLS_DEPRECATE_ISPASTTHRESHOLD(U, M, N) \ ( ( BSLS_DEPRECATE_ISNONZERO(BSLS_DEPRECATE_ISPASTTHRESHOLD_A(U)) \ && BSLS_DEPRECATE_MAKE_VER(M, N) \ <= BSLS_DEPRECATE_ISPASTTHRESHOLD_A(U)) \ || ( !BSLS_DEPRECATE_ISNONZERO(BSLS_DEPRECATE_ISPASTTHRESHOLD_A(U)) \ && BSLS_DEPRECATE_MAKE_VER(M, N) \ <= BSLS_DEPRECATE_MAKE_VER( \ BSLS_DEPRECATE_CAT(U, _VERSION_MAJOR), \ BSLS_DEPRECATE_CAT(U, _VERSION_MINOR)) - 1)) // Expand to an expression evaluating to 'true' in a preprocessor context // if the specified version 'M.N' of the specified UOR 'U' is past the // deprecation threshold for 'U', and expand to an expression evaluating to // 'false' otherwise. Version 'M.N' of 'U' is past the deprecation // threshold for 'U' if: //: o An explicit deprecation threshold has been defined for UOR 'U' and //: that threshold is greater than or equal to version 'M.N', or //: //: o An explicit deprecation threshold has *not* been defined for UOR 'U', //: the versioning package for UOR 'U' defines '<U>_VERSION_MAJOR' and //: '<U>_VERSION_MINOR', and the version so designated is greater than //: version 'M.N'. #define BSLS_DEPRECATE_ISPASTTHRESHOLD_A(U) \ BSLS_DEPRECATE_CAT(U, _VERSION_DEPRECATION_THRESHOLD) // Internal implementation machinery for 'BSLS_DEPRECATE_ISPASTTHRESHOLD'. // ========================= // BSLS_DEPRECATE_ISRETAINED // ========================= #define BSLS_DEPRECATE_ISRETAINED(U, M, N) BSLS_DEPRECATE_ISRETAINED_A(U, M, N) // Expand to an expression evaluating to 'true' in a preprocessor context // if deprecations in the specified version 'M.N' of the specified UOR 'U' // have been deactivated in this build by defining either the corresponding // 'BB_SILENCE_DEPRECATIONS_<U>_<M>_<N>' macro or the corresponding // 'BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<U>' macro, and expand to an // expression evaluating to 'false' otherwise. #define BSLS_DEPRECATE_ISRETAINED_A(U, M, N) \ BSLS_DEPRECATE_ISRETAINED_B(U, M, N) #define BSLS_DEPRECATE_ISRETAINED_B(U, M, N) \ (BSLS_DEPRECATE_ISDEFINED(BB_SILENCE_DEPRECATIONS_## U ##_## M ##_## N) \ || BSLS_DEPRECATE_ISDEFINED(BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_ ## U)) // Internal implementation machinery for 'BSLS_DEPRECATE_ISRETAINED'. // ============================================================================ // PUBLIC MACROS // ============================================================================ // ======================== // BSLS_DEPRECATE_IS_ACTIVE // ======================== #define BSLS_DEPRECATE_IS_ACTIVE(U, M, N) \ ( !BSLS_DEPRECATE_ISRETAINED(U, M, N) \ && ( BSLS_DEPRECATE_ISDEFINED(BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY)\ || BSLS_DEPRECATE_ISPASTTHRESHOLD(U, M, N))) // Expand to an expression evaluating to 'true' in a preprocessor context // if deprecations are being enforced for the specified version 'M.N' of // the specified UOR 'U', and expand to an expression evaluating to 'false' // otherwise. Deprecations will be enforced for version 'M.N' of UOR 'U' // if: //: o 'BB_SILENCE_DEPRECATIONS_<U>_<M>_<N>' has not been defined in this //: translation unit, and //: //: o 'BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<U>' has not been defined //: in this translation unit, and //: //: o One of the following holds true: //: o 'BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY' has been defined, or //: //: o An explicit deprecation threshold has been defined for UOR 'U' and //: that threshold is greater than or equal to version 'M.N', or //: //: o An explicit deprecation threshold has *not* been defined for UOR //: 'U', the versioning package for UOR 'U' defines '<U>_VERSION_MAJOR' //: and '<U>_VERSION_MINOR', and the version so designated is greater //: than version 'M.N'. #endif // INCLUDED_BSLS_DEPRECATE // ---------------------------------------------------------------------------- // Copyright 2017 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 ----------------------------------