BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_deprecate.h
Go to the documentation of this file.
1/// @file bsls_deprecate.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_deprecate.h -*-C++-*-
8#ifndef INCLUDED_BSLS_DEPRECATE
9#define INCLUDED_BSLS_DEPRECATE
10
11/// @defgroup bsls_deprecate bsls_deprecate
12/// @brief Provide machinery to deprecate interfaces on a per-version basis.
13/// @addtogroup bsl
14/// @{
15/// @addtogroup bsls
16/// @{
17/// @addtogroup bsls_deprecate
18/// @{
19///
20/// <h1> Outline </h1>
21/// * <a href="#bsls_deprecate-purpose"> Purpose</a>
22/// * <a href="#bsls_deprecate-macros"> Macros </a>
23/// * <a href="#bsls_deprecate-description"> Description </a>
24/// * <a href="#bsls_deprecate-overview-common-uses"> Overview: Common Uses </a>
25/// * <a href="#bsls_deprecate-applying-a-deprecation-tag-to-an-interface"> Applying a Deprecation Tag to an Interface </a>
26/// * <a href="#bsls_deprecate-keeping-your-code-free-of-calls-to-deprecated-interfaces"> Keeping Your Code Free of Calls to Deprecated Interfaces </a>
27/// * <a href="#bsls_deprecate-preventing-new-uses-of-already-deprecated-interfaces"> Preventing New Uses of Already-Deprecated Interfaces </a>
28/// * <a href="#bsls_deprecate-background"> Background </a>
29/// * <a href="#bsls_deprecate-mechanics"> Mechanics </a>
30/// * <a href="#bsls_deprecate-deprecation-macros"> Deprecation Macros </a>
31/// * <a href="#bsls_deprecate-version-control-macros-for-library-authors"> Version Control Macros for Library Authors </a>
32/// * <a href="#bsls_deprecate-build-control-macros-for-clients"> Build Control Macros for Clients </a>
33/// * <a href="#bsls_deprecate-supporting-compilers"> Supporting Compilers </a>
34/// * <a href="#bsls_deprecate-suggested-process-for-deprecating-code"> Suggested Process for Deprecating Code (the DeprecationDeletion Tango) </a>
35/// * <a href="#bsls_deprecate-usage"> Usage </a>
36/// * <a href="#bsls_deprecate-example-1-tagging-a-function-as-deprecated"> Example 1: Tagging a Function as Deprecated </a>
37///
38/// # Purpose {#bsls_deprecate-purpose}
39/// Provide machinery to deprecate interfaces on a per-version basis.
40///
41/// @deprecated Use @ref bsls_deprecatefeature instead.
42///
43/// # Macros {#bsls_deprecate-macros}
44///
45/// - BSLS_DEPRECATE: tag an interface as deprecated
46/// - BSLS_DEPRECATE_IS_ACTIVE: conditionally activate deprecation by UOR version
47/// - BSLS_DEPRECATE_MAKE_VER: render UOR version for deprecation threshold
48///
49/// # Description {#bsls_deprecate-description}
50/// This component defines a suite of macros to control (on a
51/// per-version, per-UOR basis) the deprecation of functions, user-defined
52/// types, and `typedef`s, and the conditional compilation of enumerators and
53/// preprocessor macros. The @ref bsls_deprecate facility operates by triggering
54/// compiler warnings when types or interfaces are used that have been tagged
55/// with deprecation macros defined by this component. Unlike previous
56/// deprecation facilities based exclusively on the use of `#ifndef` with global
57/// macros (such as `BDE_OMIT_DEPRECATED` and `BDE_OMIT_INTERNAL_DEPRECATED`),
58/// supported use of the @ref bsls_deprecate facility does *not* affect a UOR's
59/// ABI. It is therefore safe to link applications based on libraries built
60/// with different deprecation policies.
61///
62/// ## Overview: Common Uses {#bsls_deprecate-overview-common-uses}
63///
64///
65///
66/// ### Applying a Deprecation Tag to an Interface {#bsls_deprecate-applying-a-deprecation-tag-to-an-interface}
67///
68///
69/// UOR owners who wish to mark an interface as deprecated can do so by tagging
70/// the declaration of that interface with the `BSLS_DEPRECATE` macro, wrapped
71/// in a `#if` block to apply `BSLS_DEPRECATE` only when
72/// `BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)` evaluates to true for a given version
73/// `M.N` of the specified `UOR`:
74/// @code
75/// #if BSLS_DEPRECATE_IS_ACTIVE(BDE, 3, 2)
76/// BSLS_DEPRECATE
77/// #endif
78/// int foo(const char *bar);
79/// // @DEPRECATED: Use 'newFoo' instead.
80/// @endcode
81/// The above application of `BSLS_DEPRECATE_IS_ACTIVE` indicates that `foo` is
82/// deprecated starting with `bde` version 3.2. Once the deprecation threshold
83/// for `bde` advances to version 3.2, code calling `foo` will generate a
84/// deprecation warning with compilers that support deprecation attributes.
85/// (See {Version Control Macros for Library Authors} for information on
86/// defining a deprecation threshold for a UOR.) Note that in the absence of an
87/// explicit deprecation threshold (`BDE_VERSION_DEPRECATION_THRESHOLD`, in this
88/// case), code calling `foo` would begin generating deprecation warnings in the
89/// very next minor or major release of `bde` (3.3 or 4.0, whichever applies).
90///
91/// If an interface has several entities being deprecated at the same time,
92/// clients can define a new deprecation macro within that header to avoid
93/// repeated use of `BSLS_DEPRECATE_IS_ACTIVE`:
94/// @code
95/// // bdexyz_component.h -*-C++-*-
96///
97/// #if BSLS_DEPRECATE_IS_ACTIVE(BDE, 3, 2)
98/// #define BDEXYZ_COMPONENT_DEPRECATED_3_2 BSLS_DEPRECATE
99/// #else
100/// #define BDEXYZ_COMPONENT_DEPRECATED_3_2
101/// #endif
102///
103/// // ...
104///
105/// BDEXYZ_COMPONENT_DEPRECATED_3_2
106/// int foo();
107///
108/// BDEXYZ_COMPONENT_DEPRECATED_3_2
109/// int bar();
110///
111/// // ...
112///
113/// #undef BDEXYZ_COMPONENT_DEPRECATED_3_2
114/// @endcode
115///
116/// ### Keeping Your Code Free of Calls to Deprecated Interfaces {#bsls_deprecate-keeping-your-code-free-of-calls-to-deprecated-interfaces}
117///
118///
119/// When an interface is tagged with `BSLS_DEPRECATE` as shown above, the
120/// deprecation is initially <u>not</u> <u>enforced</u> by default. That is, a
121/// normal build of code calling the deprecated interface will not emit a
122/// deprecation warning.
123///
124/// Downstream developers who wish to make sure that their code uses no
125/// deprecated interfaces can do so by defining the symbol
126/// `BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY` in their build system.
127/// @code
128/// $ CXXFLAGS=-DBB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY make my_application
129///
130/// A compiler that supports `BSLS_DEPRECATE` will emit a warning if any
131/// deprecated interfaces are used in `my_application`, even if those
132/// deprecations are scheduled to take effect in a future release.
133/// @endcode
134/// **NEVER** define `BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY` in a
135/// **PRODUCTION BUILD CONFIGURATION**. If you do so, all libraries that you
136/// depend on will be prevented from deprecating more code in future versions.
137///
138/// ### Preventing New Uses of Already-Deprecated Interfaces {#bsls_deprecate-preventing-new-uses-of-already-deprecated-interfaces}
139///
140///
141/// At some point after an interface has been tagged with `BSLS_DEPRECATE`, the
142/// library owner can make new uses of that interface generate warnings by
143/// defining a deprecation threshold for the UOR that contains the deprecated
144/// interface (or by adjusting the deprecation threshold for the UOR if it
145/// already exists). Defining a deprecation threshold <u>enforces</u>
146/// deprecations made in all versions up to and including the threshold. If the
147/// version number of the deprecation threshold is greater than or equal to the
148/// version number specified in the `BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)` macro,
149/// then the `BSLS_DEPRECATE` macro will be enabled and generate a warning.
150///
151/// This is the recommended way to define a deprecation threshold (see
152/// @ref bsls_deprecate-version-control-macros-for-library-authors :
153/// @code
154/// // bdescm_versiontag.h
155///
156/// // ...
157///
158/// #define BDE_VERSION_DEPRECATION_THRESHOLD BSLS_DEPRECATE_MAKE_VER(3, 2)
159///
160/// // All 'bde' deprecations tied to release 3.2 or earlier will trigger
161/// // compiler warnings.
162/// @endcode
163///
164/// ## Background {#bsls_deprecate-background}
165///
166///
167/// Prior to the availability of this component, when a developer wanted to
168/// deprecate an API they might either apply an attribute to the API that would
169/// generate a warning, or they would use `#ifdef` to remove deprecated code
170/// when it is built with appropriate options. These solutions have a practical
171/// shortcoming in a production environment like Bloomberg's, where code changes
172/// in lower-level libraries cannot be checked in if they break the build of
173/// (higher-level) client libraries. In such a system, well-meaning clients
174/// might build their libraries using `-Werror` (to turn compilation warnings
175/// into errors) or with appropriate `#ifdef`s to ensure their code does not use
176/// deprecated APIs, but in so doing they hinder the introduction of any new
177/// deprecations. In addition, the use of `#ifdef` results in ABI compatibility
178/// issues, as some clients may build with deprecated code removed, and others
179/// may not.
180///
181/// This deprecation facility is based around two concepts that attempt to
182/// address these shortcomings:
183///
184/// 1. This facility is designed to provide ABI compatibility.
185/// `BSLS_DEPRECATE_*` macros are used to trigger *compilation* *warnings*
186/// on platforms that support deprecation attributes, instead of *removing*
187/// *code* from the codebase.
188/// 2. Typically, use of this facility will not immediately generate a warning
189/// in client code. The use of the `BSLS_DEPRECATE` macro is generally
190/// guarded by a version check using `BSLS_DEPRECATE_IS_ACTIVE`. In an
191/// environment where compiler warnings are considered to be build failures,
192/// it is possible (and encouraged) to tag a C++ entity with a deprecation
193/// macro in one release cycle, and not have that deprecation affect any
194/// clients by default until a later release cycle. During the intervening
195/// period, clients have an opportunity to proactively check their code for
196/// uses of newly-deprecated code.
197///
198/// Notice that the cost for maintaining ABI compatibility is that clients
199/// cannot check whether they are using deprecated interfaces unless they build
200/// their software on certain platforms with warnings activated. For this
201/// facility to be effective across an enterprise, it is required that such
202/// warning-enabled builds be part of the standard process for checking in code
203/// in the enterprise.
204///
205/// ## Mechanics {#bsls_deprecate-mechanics}
206///
207///
208/// This component stipulates two sets of macros. One set of deprecation
209/// macros, defined in this component, are used to identify a C++ entity as
210/// being deprecated in a given version of a given UOR. A second set of control
211/// macros, defined by clients of this component, dictates which deprecation
212/// macros are enforced at any point in the code during compilation.
213///
214/// ### Deprecation Macros {#bsls_deprecate-deprecation-macros}
215///
216///
217/// * `BSLS_DEPRECATE`
218/// > Expands to a particular deprecation attribute with compilers that have
219/// > such support; otherwise, `BSLS_DEPRECATE` expands to nothing.
220/// > `BSLS_DEPRECATE` can be applied to `class` or `struct` definitions,
221/// > function declarations, and `typedef`s.
222///
223/// * `BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)`
224/// > Expands to 1 if deprecations are enforced for the specified version
225/// > `M.N` of the specified `UOR`, and to 0 otherwise.
226///
227/// These two macros are intended to be placed together in a preprocessor `#if`
228/// block in front of a function, type, or `typedef` declaration, with
229/// `BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)` controlling whether or not
230/// `BSLS_DEPRECATE` is applied to the declaration. The exact placement of the
231/// block should match the requirements of the C++14 `[[deprecated]]` attribute.
232///
233/// Examples:
234/// @code
235/// class
236/// #if BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2)
237/// BSLS_DEPRECATE
238/// #endif
239/// SomeType {
240/// // ...
241/// };
242///
243/// struct SomeUtil {
244/// #if BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2)
245/// BSLS_DEPRECATE
246/// #endif
247/// static int someFunction();
248/// };
249///
250/// #if BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2)
251/// BSLS_DEPRECATE
252/// #endif
253/// typedef SupportedType DeprecatedType;
254/// @endcode
255/// At present, the underlying compiler intrinsics represented by
256/// `BSLS_DEPRECATE` cannot be applied uniformly to some C++ constructs, most
257/// notably variables, enumerators, and preprocessor macros. Fortunately, these
258/// constructs can often be removed from a library without otherwise affecting
259/// ABI, so `!BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)` can be used with a `#if`
260/// directive to entirely remove blocks of code containing those C++ constructs.
261///
262/// Example:
263/// @code
264/// #if !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2)
265///
266/// #define MY_DEPRECATED_MACRO
267/// // Macro definitions can be removed with 'BSLS_DEPRECATE_IS_ACTIVE'.
268///
269/// #endif // !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2)
270///
271/// namespace grppkg {
272///
273/// #if !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 3)
274///
275/// SomeType myDeprecatedGlobalVariable;
276/// // Variables at 'namespace' or global scope can be removed with
277/// // 'BSLS_DEPRECATE_IS_ACTIVE'.
278///
279/// #endif // !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 3)
280///
281/// // ...
282///
283/// } // close namespace 'grppkg'
284/// @endcode
285/// Note the use of the `!` operator: deprecated code is compiled only if
286/// deprecations are *not* enforced for the specified UOR version.
287///
288/// Particular care must be taken to ensure that deprecating one or more
289/// enumerators does not (inadvertently) change the values of other enumerators
290/// in the same `enum`:
291/// @code
292/// enum MyEnum {
293/// e_FIRST,
294/// e_SECOND,
295/// e_THIRD,
296/// #if !BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2)
297/// // These legacy enumerators can be deprecated because their removal
298/// // does not affect the values of any other enumerators.
299///
300/// FIRST = e_FIRST,
301/// SECOND = e_SECOND,
302/// THIRD = e_THIRD
303/// #endif
304/// };
305/// @endcode
306///
307/// ### Version Control Macros for Library Authors {#bsls_deprecate-version-control-macros-for-library-authors}
308///
309///
310/// A UOR-specific deprecation threshold can be (and typically *should* be)
311/// specified by the authors of a UOR to govern which of their deprecations are
312/// active by default:
313/// * `<UOR>_VERSION_DEPRECATION_THRESHOLD`
314/// > This macro should be defined in `<uor>scm_versiontag.h` alongside
315/// > `<UOR>_VERSION_MAJOR` and `<UOR>_VERSION_MINOR` to indicate the greatest
316/// > version of the unit of release `UOR` for which deprecations are enforced
317/// > by default.
318///
319/// Example:
320/// @code
321/// // abcscm_versiontag.h
322///
323/// #define ABC_VERSION_MAJOR 1
324/// #define ABC_VERSION_MINOR 4
325///
326/// #define ABC_VERSION_DEPRECATION_THRESHOLD BSLS_DEPRECATE_MAKE_VER(1, 2)
327/// @endcode
328/// In this example, `BSLS_DEPRECATE_IS_ACTIVE(ABC, M, N)` will expand to 1 for
329/// all versions `M.N` of `ABC` up to and including version 1.2. For `M.N`
330/// later than 1.2 (e.g., 1.3 or 2.0), `BSLS_DEPRECATE_IS_ACTIVE(ABC, M, N)`
331/// will expand to 1 only if the `BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY`
332/// macro is defined by the user (see {Build Control Macros for Clients}).
333///
334/// Note that if a deprecation threshold is *not* explicitly defined for a UOR
335/// that defines `<UOR>_VERSION_MAJOR` and `<UOR>_VERSION_MINOR`, then
336/// `BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N)` will expand to 1 once the version
337/// indicated by `<UOR>_VERSION_MAJOR` and `<UOR>_VERSION_MINOR` becomes greater
338/// than `M.N`. For example, `BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 4)` will expand
339/// to 1 in version 1.5 of `ABC` (or 2.0 if there is no release 1.5) if
340/// `ABC_VERSION_DEPRECATION_THRESHOLD` is not defined. For this reason, it is
341/// highly recommended that UOR authors explicitly define a deprecation
342/// threshold to avoid unexpected build failures when a new release is issued,
343/// especially in environments where warnings are considered fatal.
344///
345/// A second UOR-specific macro is available to the authors of a UOR that must,
346/// for whatever reason, continue to use interfaces that are deprecated in their
347/// own library:
348/// * `BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<UOR>`
349/// > This macro prevents @ref bsls_deprecate from enforcing deprecations for
350/// > all versions of `UOR`. This macro must be defined in each `.cpp` file
351/// > of `UOR` that either uses a deprecated interface from the *same* UOR
352/// > that has reached the deprecation threshold for `UOR`, or includes a
353/// > header file of `UOR` that uses such an interface in inline code. This
354/// > macro must be defined before the first `#include` of a header from
355/// > `UOR`.
356///
357/// Example:
358/// @code
359/// // abcxyz_somecomponent.cpp
360///
361/// #define BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_ABC
362///
363/// #include <abcxyz_somecomponent.h>
364///
365/// // ...
366/// @endcode
367///
368/// ### Build Control Macros for Clients {#bsls_deprecate-build-control-macros-for-clients}
369///
370///
371/// The following two macros are intended for client use during builds, either
372/// to *enable* *all* deprecations or to *suppress* *selected* deprecations:
373/// * `BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY`
374/// > This macro should be defined as a `-D` parameter during test builds of
375/// > components that are intended to be deprecation-clean. When this macro
376/// > is defined, deprecations will be enforced for all versions of all UORs,
377/// > except as overridden by `BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<UOR>`
378/// > (see @ref bsls_deprecate-version-control-macros-for-library-authors or
379/// > `BB_SILENCE_DEPRECATIONS_<UOR>_<M>_<N>` (see below). This macro must
380/// > **never** appear in source code, and must **never** be defined for any
381/// > production or check-in build configuration.
382///
383/// * `BB_SILENCE_DEPRECATIONS_<UOR>_<M>_<N>`
384/// > This macro should be defined by clients of `UOR` who still need to use
385/// > an interface that was deprecated in version `M.N` after the deprecation
386/// > threshold for `UOR` has reached (or exceeded) `M.N`. This macro should
387/// > be defined *before* the first `#include` of a header from `UOR`. This
388/// > macro must *never* be defined in a header file.
389///
390/// Example:
391/// @code
392/// // grppkg_fooutil.cpp
393///
394/// /// `BB_SILENCE_DEPRECATIONS_ABC_1_2` must be defined before the
395/// /// component`s own `#include` directive in case `grppkg_fooutil.h`
396/// /// includes headers from `abc` (directly or transitively).
397/// #define BB_SILENCE_DEPRECATIONS_ABC_1_2
398///
399/// #include <grppkg_fooutil.h>
400///
401/// // Interfaces from 'abcxyz_someutil' deprecated in version 1.2 of 'abc'
402/// // will not trigger compiler warnings when used in 'grppkg_fooutil.cpp'.
403///
404/// #include <abcxyz_someutil.h>
405/// ...
406///
407/// namespace grppkg {
408///
409/// void FooUtil::foo()
410/// {
411/// int result = abcxyz::SomeUtil::someFunction();
412/// // ...
413/// }
414///
415/// } // close package namespace
416/// @endcode
417///
418/// ## Supporting Compilers {#bsls_deprecate-supporting-compilers}
419///
420///
421/// `BSLS_DEPRECATE` will produce a warning with the following compilers:
422/// * gcc 4.3+
423/// * clang 3.4+
424/// * Xcode 4.4+
425/// * Microsoft Visual Studio 2010 or later
426///
427/// Additionally, `BSLS_DEPRECATE` will produce a warning with any compiler that
428/// provides the C++14 `deprecated` attribute.
429///
430/// ## Suggested Process for Deprecating Code (the DeprecationDeletion Tango) {#bsls_deprecate-suggested-process-for-deprecating-code}
431///
432///
433/// Deprecation is a negotiation process between code authors and code consumers
434/// to allow old code to be removed from the codebase. This component supports
435/// a deprecation model where code moves through four steps from being fully
436/// supported, to optionally deprecated, to fully deprecated, and finally to
437/// being deleted. At each step, responsibility for moving the process forward
438/// is passed back and forth between library authors and library users.
439///
440/// When the owners of a library want to deprecate an interface, they start by
441/// adding appropriate deprecation macros, specifying their UOR and the version
442/// of their next release. For example, suppose package group `abc` is
443/// currently at version 1.1. If the owners of `abc` want to deprecate a
444/// function `abcxyz::SomeUtil::someFunction`, they could add the deprecation
445/// macros `BSLS_DEPRECATE` and `BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2)` in front
446/// of the declaration of `someFunction`:
447/// @code
448/// // abcxyz_someutil.h
449///
450/// ...
451///
452/// struct SomeUtil {
453///
454/// ...
455///
456/// /// @DEPRECATED: use 'abcdef::OtherUtil::otherFunction' instead.
457/// #if BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2)
458/// BSLS_DEPRECATE
459/// #endif
460/// static int someFunction();
461///
462/// ...
463///
464/// };
465/// @endcode
466/// At this point deprecations are not enforced by default for version 1.2 of
467/// `abc`, so the deprecation macro alone will not have any affect on clients.
468/// A client building their code normally will trigger no compiler warnings due
469/// to this new deprecation:
470/// @code
471/// $ make grppkg_fooutil
472/// ... dependencies: abc version 1.2 ...
473/// ... no warnings ...
474/// @endcode
475/// If the owners of a client library or application want to check that their
476/// code uses no deprecated interfaces, they can define the
477/// `BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY` flag in their *test* build
478/// process. A compiler that supports deprecation attributes will then trigger
479/// compiler warnings:
480/// @code
481/// $ CXXFLAGS=-DBB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY make grppkg_fooutil
482/// ... dependencies: abc version 1.2 ...
483/// grppkg_fooutil.cpp:43: warning: function 'abcxyz::SomeUtil::someFunction'
484/// is explicitly deprecated.
485/// @endcode
486/// **WARNING**: Clients at Bloomberg *must* *not* define
487/// `BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY` in a production build. This
488/// flag should be used for development builds only.
489///
490/// Now the owners have the opportunity to fix their code by removing the
491/// dependency on `abcxyz::SomeUtil::someFunction`.
492///
493/// At some point in the future, possibly on release of `abc` version 1.3, the
494/// owners of `abc` will make deprecations enforced by default for version 1.2
495/// of `abc`, by setting the deprecation threshold for `abc` in their version
496/// control headers:
497/// @code
498/// // abcscm_versiontag.h
499///
500/// #define ABC_VERSION_MAJOR 1
501/// #define ABC_VERSION_MINOR 3
502///
503/// ...
504///
505/// #define ABC_VERSION_DEPRECATION_THRESHOLD BSLS_DEPRECATE_MAKE_VER(1, 2)
506/// @endcode
507/// If the owners of `grp` have cleaned up their code, normal builds will
508/// trigger no compiler warnings. However, any new development by any clients
509/// will trigger warnings if they add a new use of
510/// `abcxyz::SomeUtil::someFunction`:
511/// @code
512/// $ make foobar_bazutil
513/// ... dependencies: abc version 1.3 ...
514/// foobar_bazutil.cpp:177: warning: function 'abcxyz::SomeUtil::someFunction'
515/// is explicitly deprecated.
516/// @endcode
517/// But what if the owners of `grp` will not, or for some reason cannot, clean
518/// up their code in the near term? Moving the threshold for `abc` to version
519/// 1.2 will of course trigger warnings when the owners of `grp` next try to
520/// build @ref grppkg_fooutil . In a development context requiring that all
521/// production builds remain warning-free, we would be at an impasse: either the
522/// owners of `grp` must clean up their code immediately, or the owners of `abc`
523/// will not be able to enforce deprecations by default for version 1.2.
524///
525/// This impasse can be resolved by allowing the owners of `grp` to locally
526/// silence warnings caused by deprecations for version 1.2 of `abc`. This is
527/// done by adding a definition of `BB_SILENCE_DEPRECATIONS_ABC_1_2` to any
528/// `.cpp` files that use `abcxyz::SomeUtil::someFunction`:
529/// @code
530/// // grppkg_fooutil.cpp
531/// #define BB_SILENCE_DEPRECATIONS_ABC_1_2
532///
533/// ...
534/// @endcode
535/// Now the entire codebase can build warning-free again.
536///
537/// Managers can easily detect `BB_SILENCE_DEPRECATIONS_<UOR>_<M>_<N>` macros in
538/// the codebase, and put pressure on teams to remove such remnant uses of
539/// deprecated code. When all remnant uses have been removed, then the
540/// deprecated function can be deleted entirely:
541/// @code
542/// // abcxyz_someutil.h
543///
544/// ...
545///
546/// struct SomeUtil {
547///
548/// ...
549///
550/// // RIP: The function formerly known as 'someFunction'.
551///
552/// ...
553///
554/// };
555/// @endcode
556///
557/// ## Usage {#bsls_deprecate-usage}
558///
559///
560/// This section illustrates intended use of this component.
561///
562/// ### Example 1: Tagging a Function as Deprecated {#bsls_deprecate-example-1-tagging-a-function-as-deprecated}
563///
564///
565/// When one piece of code has been superseded by another, we would like to get
566/// users to adopt the new code and stop using the old code. Being able to
567/// inform clients that they need to clean up existing uses of the old code, and
568/// also to prevent *new* uses of that code, makes it easier to get to the point
569/// where old code actually has zero uses and can be deleted. The deprecation
570/// macros `BSLS_DEPRECATE` and `BSLS_DEPRECATE_IS_ACTIVE`, and their associated
571/// control macros, can be used to gradually reduce the number of uses of
572/// deprecated code, so that it can be removed eventually.
573///
574/// Suppose we own package group `xxx` that is currently at version 7.6. One of
575/// our components contains a function `foo` that has been superseded by another
576/// function `bar`.
577/// @code
578/// /// Load into the specified `coefficient` the (positive) Winkelbaum
579/// /// Coefficient of the specified `n`. Return 0 on success, and a
580/// /// negative number if there is no coefficient corresponding to `n`.
581/// /// Note that every integer divisible by the Winkelbaum Modulus (17) has
582/// /// a corresponding Winkelbaum Coefficient.
583/// int foo(int *coefficient, int n);
584///
585/// // ...
586///
587/// /// Return the (positive) Winkelbaum Coefficient of the specified `n`.
588/// /// The behavior is undefined unless `n` is divisible by 17 (the
589/// /// Winkelbaum Modulus).
590/// int bar(int n);
591/// @endcode
592/// First, we add a deprecation tag to the declaration of `foo`, showing that it
593/// will be deprecated starting with version 7.7, and update the documentation
594/// accordingly:
595/// @code
596/// /// Load into the specified `coefficient` the (positive) Winkelbaum
597/// /// Coefficient of the specified `n`. Return 0 on success, and a
598/// /// negative number if there is no coefficient corresponding to `n`.
599/// /// Note that every integer divisible by the Winkelbaum Modulus (17) has
600/// /// a corresponding Winkelbaum Coefficient.
601/// ///
602/// /// @DEPRECATED: Use `bar` instead.
603/// #if BSLS_DEPRECATE_IS_ACTIVE(XXX, 7, 7)
604/// BSLS_DEPRECATE
605/// #endif
606/// int foo(int *coefficient, int n);
607///
608/// // ...
609///
610/// /// Return the (positive) Winkelbaum Coefficient of the specified `n`.
611/// /// The behavior is undefined unless `n` is divisible by 17 (the
612/// /// Winkelbaum Modulus).
613/// int bar(int n);
614/// @endcode
615/// When we release version 7.7, the added deprecation tag will not immediately
616/// affect any of the users of `foo`. However if any of those users do a test
617/// build of their code with `-DBB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY`, they
618/// will see a warning that `foo` has been deprecated.
619///
620/// Finally, when enough time has passed to allow all users of `foo` to switch
621/// over to using `bar`, probably on or after the release of `xxx` version 7.8,
622/// we can enforce the deprecation of `foo` by moving the deprecation threshold
623/// for `xxx` to version 7.7, to indicate that all interfaces deprecated for
624/// version 7.7 are disallowed by default:
625/// @code
626/// // xxxscm_versiontag.h
627///
628/// #define XXX_VERSION_MAJOR 7
629/// #define XXX_VERSION_MINOR 8
630///
631/// // ...
632///
633/// #define XXX_VERSION_DEPRECATION_THRESHOLD BSLS_DEPRECATE_MAKE_VER(7, 7)
634/// @endcode
635/// @}
636/** @} */
637/** @} */
638
639/** @addtogroup bsl
640 * @{
641 */
642/** @addtogroup bsls
643 * @{
644 */
645/** @addtogroup bsls_deprecate
646 * @{
647 */
648
649 // ==============
650 // BSLS_DEPRECATE
651 // ==============
652
653// First, try to determine if the C++14 'deprecated' attribute is supported,
654// using standard feature-detection facilities. Note that Sun CC breaks this
655// detection by defining a macro called '__has_cpp_attribute' that reports
656// compile-errors rather than returning a 0 literal when called with
657// 'deprecated'.
658
659#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C)
660// Check the Sun compiler macros directly, rather than rely on the BDE
661// platform-detection macros in @ref bsls_platform , to allow deprecation of
662// features in that component in the future. This feature was last
663// tested with CC 12.5.
664
665#if defined(__has_cpp_attribute)
666# if __has_cpp_attribute(deprecated)
667# define BSLS_DEPRECATE [[deprecated]]
668
669# if defined(__clang__) && __cplusplus < 201402L
670// Clang issues a warning when the C++14 attribute is used before C++14,
671// where it is offered as an extension rather than a feature.
672# undef BSLS_DEPRECATE
673# endif
674
675# if defined(__GNUC__) && __cplusplus < 201103L
676// G++ passes the '__has_cpp_attribute(deprecated)' test, but still
677// produces an error when '[[deprecated]]' is used in non-C++11 mode.
678# undef BSLS_DEPRECATE
679# endif
680
681# endif
682#endif
683
684// Then, try to determine if a GCC-style deprecation attribute is supported,
685// using semi-standard feature-detection facilities.
686
687#ifndef BSLS_DEPRECATE
688# if defined(__has_attribute)
689# if __has_attribute(deprecated)
690# define BSLS_DEPRECATE __attribute__ ((deprecated))
691# endif
692# endif
693#endif
694
695#endif // Sun-avoidance
696
697// Next, define non-standard attributes for platforms known to support them.
698
699#ifndef BSLS_DEPRECATE
700# if defined(__GNUC__)
701// All compilers in the GNUC interface family (g++ and clang) provide the
702// simple gcc extension attribute.
703# define BSLS_DEPRECATE __attribute__ ((deprecated))
704# elif defined (_MSC_VER)
705// All versions of MSVC supported by BDE provide a 'deprecate' declaration
706// specifier.
707# define BSLS_DEPRECATE __declspec(deprecated)
708# endif
709#endif
710
711// Finally, record whether the current compiler supports some form of
712// deprecation attribute.
713
714#ifdef BSLS_DEPRECATE
715# define BSLS_DEPRECATE_COMPILER_SUPPORT 1
716#else
717# define BSLS_DEPRECATE_COMPILER_SUPPORT 0
718// Provide a fallback empty definition when the compiler does not support
719// deprecation attributes.
720# define BSLS_DEPRECATE
721#endif
722
723// ============================================================================
724// INTERNAL MACHINERY
725// ============================================================================
726
727 // ==================
728 // BSLS_DEPRECATE_CAT
729 // ==================
730
731/// Expand to the expansion of the specified `X`, joined to the expansion of
732/// the specified `Y`.
733#define BSLS_DEPRECATE_CAT(X, Y) BSLS_DEPRECATE_CAT_A(X, Y)
734
735#define BSLS_DEPRECATE_CAT_A(X, Y) BSLS_DEPRECATE_CAT_B(X, Y)
736/// Internal implementation machinery for `BSLS_DEPRECATE_CAT`.
737#define BSLS_DEPRECATE_CAT_B(X, Y) X ## Y
738
739 // ========================
740 // BSLS_DEPRECATE_ISDEFINED
741 // ========================
742
743/// Expand to an expression evaluating to `true` in a preprocessor context
744/// if the deprecation control macro symbol supplied as an argument has been
745/// `#define`d as nil, 0, or 1, and expand to an expression evaluating to
746/// `false` otherwise. The behavior is undefined unless this macro is
747/// evaluated with a single argument having the form of a deprecation
748/// control macro symbol, and that symbol has either not been `#define`d at
749/// all or has been `#define`d as nil, 0, or 1.
750#define BSLS_DEPRECATE_ISDEFINED(...) BSLS_DEPRECATE_ISDEFINED_A(__VA_ARGS__)
751
752/// Internal implementation machinery for `BSLS_DEPRECATE_ISDEFINED`.
753#define BSLS_DEPRECATE_ISDEFINED_A(...) ((__VA_ARGS__ ## 1L) != 0)
754
755 // ========================
756 // BSLS_DEPRECATE_ISNONZERO
757 // ========================
758
759/// Expand to an expression evaluating to `true` in a preprocessor context
760/// if the deprecation control macro symbol supplied as an argument has been
761/// `#define`d as an expression that evaluates to a non-zero value, and
762/// expand to an expression evaluating to `false` otherwise. The behavior
763/// is undefined unless this macro is evaluated with a single argument
764/// having the form of a deprecation control macro symbol, and that symbol
765/// has either not been `#define`d at all, or has been `#define`d as nil or
766/// an arithmetic expression.
767#define BSLS_DEPRECATE_ISNONZERO(...) BSLS_DEPRECATE_ISNONZERO_A(__VA_ARGS__)
768
769/// Internal implementation machinery for `BSLS_DEPRECATE_ISNONZERO`.
770#define BSLS_DEPRECATE_ISNONZERO_A(...) (__VA_ARGS__ + 1 != 1)
771
772 // =======================
773 // BSLS_DEPRECATE_MAKE_VER
774 // =======================
775
776/// Expand to an opaque sequence of symbols encoding a UOR version where
777/// the specified `M` is the major version number and the specified `N` is
778/// the minor version number.
779#define BSLS_DEPRECATE_MAKE_VER(M, N) ((M) * 1000 + (N))
780
781 // ==============================
782 // BSLS_DEPRECATE_ISPASTTHRESHOLD
783 // ==============================
784
785/// Expand to an expression evaluating to `true` in a preprocessor context
786/// if the specified version `M.N` of the specified UOR `U` is past the
787/// deprecation threshold for `U`, and expand to an expression evaluating to
788/// `false` otherwise. Version `M.N` of `U` is past the deprecation
789/// threshold for `U` if:
790/// * An explicit deprecation threshold has been defined for UOR `U` and
791/// that threshold is greater than or equal to version `M.N`, or
792/// * An explicit deprecation threshold has *not* been defined for UOR `U`,
793/// the versioning package for UOR `U` defines `<U>_VERSION_MAJOR` and
794/// `<U>_VERSION_MINOR`, and the version so designated is greater than
795/// version `M.N`.
796#define BSLS_DEPRECATE_ISPASTTHRESHOLD(U, M, N) \
797 ( ( BSLS_DEPRECATE_ISNONZERO(BSLS_DEPRECATE_ISPASTTHRESHOLD_A(U)) \
798 && BSLS_DEPRECATE_MAKE_VER(M, N) \
799 <= BSLS_DEPRECATE_ISPASTTHRESHOLD_A(U)) \
800 || ( !BSLS_DEPRECATE_ISNONZERO(BSLS_DEPRECATE_ISPASTTHRESHOLD_A(U)) \
801 && BSLS_DEPRECATE_MAKE_VER(M, N) \
802 <= BSLS_DEPRECATE_MAKE_VER( \
803 BSLS_DEPRECATE_CAT(U, _VERSION_MAJOR), \
804 BSLS_DEPRECATE_CAT(U, _VERSION_MINOR)) - 1))
805
806/// Internal implementation machinery for `BSLS_DEPRECATE_ISPASTTHRESHOLD`.
807#define BSLS_DEPRECATE_ISPASTTHRESHOLD_A(U) \
808 BSLS_DEPRECATE_CAT(U, _VERSION_DEPRECATION_THRESHOLD)
809
810 // =========================
811 // BSLS_DEPRECATE_ISRETAINED
812 // =========================
813
814/// Expand to an expression evaluating to `true` in a preprocessor context
815/// if deprecations in the specified version `M.N` of the specified UOR `U`
816/// have been deactivated in this build by defining either the corresponding
817/// `BB_SILENCE_DEPRECATIONS_<U>_<M>_<N>` macro or the corresponding
818/// `BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<U>` macro, and expand to an
819/// expression evaluating to `false` otherwise.
820#define BSLS_DEPRECATE_ISRETAINED(U, M, N) BSLS_DEPRECATE_ISRETAINED_A(U, M, N)
821
822#define BSLS_DEPRECATE_ISRETAINED_A(U, M, N) \
823 BSLS_DEPRECATE_ISRETAINED_B(U, M, N)
824/// Internal implementation machinery for `BSLS_DEPRECATE_ISRETAINED`.
825#define BSLS_DEPRECATE_ISRETAINED_B(U, M, N) \
826 (BSLS_DEPRECATE_ISDEFINED(BB_SILENCE_DEPRECATIONS_## U ##_## M ##_## N) \
827 || BSLS_DEPRECATE_ISDEFINED(BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_ ## U))
828
829// ============================================================================
830// PUBLIC MACROS
831// ============================================================================
832
833 // ========================
834 // BSLS_DEPRECATE_IS_ACTIVE
835 // ========================
836
837/// Expand to an expression evaluating to `true` in a preprocessor context
838/// if deprecations are being enforced for the specified version `M.N` of
839/// the specified UOR `U`, and expand to an expression evaluating to `false`
840/// otherwise. Deprecations will be enforced for version `M.N` of UOR `U`
841/// if:
842/// * `BB_SILENCE_DEPRECATIONS_<U>_<M>_<N>` has not been defined in this
843/// translation unit, and
844/// * `BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<U>` has not been defined
845/// in this translation unit, and
846/// * One of the following holds true:
847/// - `BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY` has been defined, or
848/// - An explicit deprecation threshold has been defined for UOR `U` and
849/// that threshold is greater than or equal to version `M.N`, or
850/// - An explicit deprecation threshold has *not* been defined for UOR
851/// `U`, the versioning package for UOR `U` defines `<U>_VERSION_MAJOR`
852/// and `<U>_VERSION_MINOR`, and the version so designated is greater
853/// than version `M.N`.
854#define BSLS_DEPRECATE_IS_ACTIVE(U, M, N) \
855 ( !BSLS_DEPRECATE_ISRETAINED(U, M, N) \
856 && ( BSLS_DEPRECATE_ISDEFINED(BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY)\
857 || BSLS_DEPRECATE_ISPASTTHRESHOLD(U, M, N)))
858
859#endif // INCLUDED_BSLS_DEPRECATE
860
861// ----------------------------------------------------------------------------
862// Copyright 2017 Bloomberg Finance L.P.
863//
864// Licensed under the Apache License, Version 2.0 (the "License");
865// you may not use this file except in compliance with the License.
866// You may obtain a copy of the License at
867//
868// http://www.apache.org/licenses/LICENSE-2.0
869//
870// Unless required by applicable law or agreed to in writing, software
871// distributed under the License is distributed on an "AS IS" BASIS,
872// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
873// See the License for the specific language governing permissions and
874// limitations under the License.
875// ----------------------------- END-OF-FILE ----------------------------------
876
877/** @} */
878/** @} */
879/** @} */