BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bsls_deprecatefeature.h
Go to the documentation of this file.
1/// @file bsls_deprecatefeature.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_deprecatefeature.h -*-C++-*-
8#ifndef INCLUDED_BSLS_DEPRECATEFEATURE
9#define INCLUDED_BSLS_DEPRECATEFEATURE
10
11/// @defgroup bsls_deprecatefeature bsls_deprecatefeature
12/// @brief Provide machinery to deprecate entities in C++ code.
13/// @addtogroup bsl
14/// @{
15/// @addtogroup bsls
16/// @{
17/// @addtogroup bsls_deprecatefeature
18/// @{
19///
20/// <h1> Outline </h1>
21/// * <a href="#bsls_deprecatefeature-purpose"> Purpose</a>
22/// * <a href="#bsls_deprecatefeature-macros"> Macros </a>
23/// * <a href="#bsls_deprecatefeature-description"> Description </a>
24/// * <a href="#bsls_deprecatefeature-concerns-with-compiler-warnings"> Concerns with Compiler Warnings </a>
25/// * <a href="#bsls_deprecatefeature-macro-reference"> Macro Reference </a>
26/// * <a href="#bsls_deprecatefeature-configuration-reference"> Configuration Reference </a>
27/// * <a href="#bsls_deprecatefeature-usage"> Usage </a>
28/// * <a href="#bsls_deprecatefeature-example-1-deprecating-a-feature"> Example 1: Deprecating a Feature </a>
29/// * <a href="#bsls_deprecatefeature-example-2-deprecating-a-feature-across-multiple-headers"> Example 2: Deprecating a Feature Across Multiple Headers </a>
30/// * <a href="#bsls_deprecatefeature-example-3-deprecating-a-header"> Example 3: Deprecating a Header </a>
31///
32/// # Purpose {#bsls_deprecatefeature-purpose}
33/// Provide machinery to deprecate entities in C++ code.
34///
35/// # Macros {#bsls_deprecatefeature-macros}
36///
37/// - BSLS_DEPRECATE_FEATURE: mark a C++ entity as deprecated
38/// - BSLS_DEPRECATE_FEATURE_HEADER: mark entire header file as deprecated
39///
40/// # Description {#bsls_deprecatefeature-description}
41/// This component provides facilities to identify deprecated C++
42/// entities. The deprecation annotations supplied by this component may,
43/// depending on the build configuration, instantiate as C++ `[[deprecated]]`
44/// annotations for which the compiler will emit a warning. Each deprecated
45/// entity annotated by the macros in this component is identified by a `UOR`
46/// and `FEATURE`, allowing the use of that deprecated entity to be more easily
47/// uniquely identified and tracked over time via tooling. Here "UOR" means
48/// Unit-Of-Release, which is typically a package, package-group or library.
49///
50/// **WARNING**: The build configuration flag,
51/// `BB_DEPRECATE_ENABLE_ALL_DEPRECATIONS_FOR_TESTING`, that enables compiler
52/// warnings for `BSLS_DEPRECATE_FEATURE` should not be used in
53/// cross-organizational integration builds such as a production `unstable`
54/// dpkg build.
55///
56/// ## Concerns with Compiler Warnings {#bsls_deprecatefeature-concerns-with-compiler-warnings}
57///
58///
59/// In large development organization, where many teams may enable "warnings as
60/// errors", enabling deprecation warnings in a cross-organizational integration
61/// build will frequently prevent lower-level software from applying the
62/// deprecation annotation to any newly deprecated code.
63///
64/// Instead this component is designed to support static analysis tools that
65/// identify deprecated entities, and allow them to be tracked and reported by
66/// systems outside of the normal compilation process. The expectation is that
67/// developers would use configuration options that generate compiler warnings
68/// in local builds when they are actively working to remove the use of
69/// deprecated code.
70///
71/// ## Macro Reference {#bsls_deprecatefeature-macro-reference}
72///
73///
74/// This section documents the preprocessor macros defined in this component.
75///
76/// * `BSLS_DEPRECATE_FEATURE(UOR, FEATURE, MESSAGE)`
77/// > This macro is used to annotate code to indicate that a name or entity
78/// > has been deprecated, and is associated with the specified `UOR`
79/// > (Unit-Of-Release), deprecated `FEATURE`, and `MESSAGE`. This macro can
80/// > be used as if it were the C++ standard attribute `[[deprecated]]`, and
81/// > in appropriate build configurations will instantiate as a C++
82/// > `[[deprecated]]` annotation. `UOR` and `FEATURE` are character strings
83/// > intended to uniquely identify one or more related entities that have
84/// > been deprecated. `MESSAGE` is a descriptive text intended for the a
85/// > user of the deprecated feature (for example informing them of a
86/// > replacement feature). For example, if several of the date and time
87/// > types in the `bde` library were deprecated they might be marked with the
88/// > annotation:
89/// > `BSLS_DEPRECATE_FEATURE("bde", "date-and-time", "Use bdlt instead")`.
90/// > `UOR` and `FEATURE` are meant to help uniquely identify a deprecation in
91/// > external systems (e.g., a dashboard monitoring the state of a
92/// > deprecation) so the supplied strings should start with a letter, and
93/// > contain only letters, numbers, underscore, and dash characters (i.e.,
94/// > matching the regular expression "[a-zA-Z][\w\-]*").
95///
96/// * `BSLS_DEPRECATE_FEATURE_IS_SUPPORTED`
97/// > This macro is defined if the current platform supports instantiating the
98/// > deprecation annotation macros into annotation understood by the
99/// > compiler.
100///
101/// * `BSLS_DEPRECATE_FEATURE_ANNOTATION_IS_ACTIVE`
102/// > This macro is defined if deprecation annotation macros defined in this
103/// > component *will* be instantiated into annotations understood by the
104/// > compiler (i.e., this will be defined if
105/// > `BSLS_DEPRECATE_FEATURE_SUPPORTED_PLATFORM` is defined and the build
106/// > configuration macros are configured in a way that the annotations will
107/// > instantiate as the `[[deprecated]]` attribute).
108///
109/// * `BSLS_DEPRECATE_FEATURE_HEADER(UOR, FEATURE, MESSAGE)`
110/// > This macro is used to annotate a header file to indicate that header
111/// > has been deprecated, and is associated with the specified `UOR`
112/// > (Unit-Of-Release), deprecated `FEATURE`, and `MESSAGE`. This macro can
113/// > be used for the headers that contain no actual code to generate compile
114/// > warning when the header is included.
115///
116/// ## Configuration Reference {#bsls_deprecatefeature-configuration-reference}
117///
118///
119/// There are a set of macros, not defined by this component, that users may
120/// supply (e.g., to their build system) to configure the behavior of the
121/// deprecation annotation macros provided by this component.
122///
123/// The available configuration macros are described below:
124/// * `BB_DEPRECATE_ENABLE_ALL_DEPRECATIONS_FOR_TESTING`
125/// > This macro, when
126/// > defined, enables the instantiation of every deprecation macro as a C++
127/// > `[[deprecated]]` annotation. This *MUST* *NOT* be defined as part of
128/// > cross-organization integration build such as an 'unstable' dpkg build
129/// > (see {Concerns with Compiler Warnings}).
130///
131/// * `BB_DEPRECATE_ENABLE_JSON_MESSAGE`
132/// > Changes the messages reported by compiler deprecation annotations to be
133/// > a JSON document intended to be useful for tools looking to identify and
134/// > categorize deprecations.
135///
136/// * `BSLS_DEPRECATE_FEATURE_ENABLE_ALL_DEPRECATIONS_FOR_TESTING`
137/// > This macro is a synonym for
138/// > `BB_DEPRECATE_ENABLE_ALL_DEPRECATIONS_FOR_TESTING`.
139///
140/// * `BSLS_DEPRECATE_FEATURE_ENABLE_JSON_MESSAGE`
141/// > This macro is a synonym for `BB_DEPRECATE_ENABLE_JSON_MESSAGE`.
142///
143/// ## Usage {#bsls_deprecatefeature-usage}
144///
145///
146/// In this section we show intended usage of this component.
147///
148/// ### Example 1: Deprecating a Feature {#bsls_deprecatefeature-example-1-deprecating-a-feature}
149///
150///
151/// The following example demonstrates using the `BSLS_DEPRECATE_FEATURE` macro
152/// to deprecate several C++ entities.
153///
154/// The `BSLS_DEPRECATE_FEATURE` macro can be applied in the same way as the C++
155/// `[[deprecated]]` annotation. For example, imagine we are deprecating a
156/// function `oldFunction` in the `bsl` library as part of migrating software to
157/// the linux platform, we might write:
158/// @code
159/// BSLS_DEPRECATE_FEATURE("bsl", "oldFunction", "Use newFunction instead")
160/// void oldFunction();
161/// @endcode
162/// Here the string "bsl" refers to the library or Unit-Of-Release (UOR) that
163/// the deprecation occurs in. "oldFunction" is an arbitrary identifier for
164/// the feature being deprecated. Together the `UOR` and `FEATURE` are
165/// intended to form a unique enterprise-wide identifier for the feature being
166/// deprecated. Finally the string "Use newFunction instead" is a message for
167/// users of the deprecated feature.
168///
169/// Marking `oldFunction` in this way makes the deprecation of `oldFunction`
170/// visible to code analysis tools. In addition, in a local build, warnings
171/// for uses of the deprecated entity can be enabled using a build macro
172/// `BB_DEPRECATE_ENABLE_ALL_DEPRECATIONS_FOR_TESTING` (this macro *MUST* *NOT*
173/// be used as part of a cross-organization integration build such as a
174/// `unstable` dpkg build, see {Concerns with Compiler Warnings}).
175///
176/// Similarly, if we were deprecating a class `OldType` we might write:
177/// @code
178///
179/// /// ...
180/// class BSLS_DEPRECATE_FEATURE("bsl", "OldType", "Use NewType instead")
181/// OldType {
182/// };
183/// @endcode
184/// Frequently, more than one C++ related entity may be associated with a
185/// deprecated feature. In that case we would want to use the same identifier
186/// for each entity we mark deprecated. To simplify this we might create a
187/// deprecation macro that is local to the component. For example, if we were
188/// deprecating a queue and its iterator in the `bde` library we might write:
189/// @code
190/// #define BDEC_QUEUE_DEPRECATE \.
191/// BSLS_DEPRECATE_FEATURE("bde", "bdec_queue", "Use bsl::queue instead")
192///
193/// /// ...
194/// class BDEC_QUEUE_DEPRECATE bdec_Queue {
195/// };
196///
197/// /// ...
198/// class BDEC_QUEUE_DEPRECATE bdec_QueueIterator {
199/// };
200/// @endcode
201/// Sometimes several entities are deprecated as part of the same feature where
202/// separate messages are appropriate. For example, imagine we had a component
203/// @ref bsls_measurementutil that we were converting from imperial to metric
204/// units:
205/// @code
206/// #define BSLS_MEASUREMEANTUTIL_DEPRECATE_IMPERIAL(MESSAGE) \.
207/// BSLS_DEPRECATE_FEATURE("bsl", "deprecate-imperial-units", MESSAGE)
208///
209/// struct MeasurementUtil {
210///
211/// BSLS_MEASUREMEANTUTIL_DEPRECATE_IMPERIAL("Use getKilometers instead")
212/// static double getMiles();
213///
214/// BSLS_MEASUREMEANTUTIL_DEPRECATE_IMPERIAL("Use getKilograms instead")
215/// static double getPounds();
216/// };
217/// @endcode
218///
219/// ### Example 2: Deprecating a Feature Across Multiple Headers {#bsls_deprecatefeature-example-2-deprecating-a-feature-across-multiple-headers}
220///
221///
222/// Frequently a feature being deprecated may span multiple components. For
223/// example, we may want to deprecate all the date and time types in the `bde`
224/// library. In those instances one may define a macro in the lowest level
225/// component (e.g., define `BDET_DATE_DEPRECATE_DATE_AND_TIME` in @ref bdet_date ).
226/// Alternatively, one might create a component specifically for the deprecation
227/// (e.g., define `BDET_DEPRECATE_DATE_AND_TIME` in a newly created
228/// @ref bdet_deprecate component). The following code shows the latter, creating
229/// a new component, @ref bdet_deprecate in which to provide macros to deprecate
230/// code across `bdet`.
231///
232/// First, we create a new component, @ref bdet_deprecate and define the following
233/// macro:
234/// @code
235/// // bdet_deprecate.h
236///
237/// #define BDET_DEPRECATE_DATE_AND_TIME(MESSAGE) \.
238/// BSLS_DEPRECATE_FEATURE("bde", "date-and-time", MESSAGE)
239/// @endcode
240/// We can use that macro to mark various components deprecated. Next, we mark
241/// an old type name as deprecated:
242/// @code
243/// // bdet_date.h
244///
245/// BDET_DEPRECATE_DATE_AND_TIME("Use bdlt::Date") typedef bdlt::Date Date;
246/// @endcode
247/// Then we mark a class declaration as deprecated:
248/// @code
249/// // bdet_calendar.h
250///
251/// /// ...
252/// class BDET_DEPRECATE_DATE_AND_TIME("Use bdlt::PackedCalendar") Calendar {
253/// };
254/// @endcode
255/// Finally we mark a function as deprecated:
256/// @code
257/// // bdet_dateimputil.h
258///
259/// struct DateUtil {
260///
261/// BDET_DEPRECATE_DATE_AND_TIME("Use bdlt::DateUtil instead")
262/// static bool isValidYYYYMMDD(int yyyymmddValue);
263///
264/// // ...
265/// };
266/// @endcode
267/// ### Example 3: Deprecating a Header {#bsls_deprecatefeature-example-3-deprecating-a-header}
268///
269///
270/// Once all the deprecated features has been removed from a header, the header
271/// itself cannot be removed as long as there are `#include`s with the header.
272/// To warn user about including the obsolete header, use the
273/// `BSLS_DEPRECATE_FEATURE_HEADER` macro:
274/// @code
275/// // bdet_date.h
276///
277/// #include <bsls_deprecatefeature.h>
278///
279/// BSLS_DEPRECATE_FEATURE_HEADER("bdet",
280/// "bdet_date",
281/// "Do not include obsolete bdet_date.h");
282/// @endcode
283/// @}
284/** @} */
285/** @} */
286
287/** @addtogroup bsl
288 * @{
289 */
290/** @addtogroup bsls
291 * @{
292 */
293/** @addtogroup bsls_deprecatefeature
294 * @{
295 */
296
297 // ==============================
298 // Component Configuration Macros
299 // ==============================
300
301// This could be replaced with BSLS_COMPILERFEATURES_CPLUSPLUS, but for the
302// moment, this header has 0 dependencies, which may be a useful feature to
303// maintain.
304
305#if (defined(__cplusplus) && (__cplusplus >= 201703L)) || \
306 (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))
307#define BSLS_DEPRECATE_FEATURE_IS_SUPPORTED
308#endif
309
310#if defined(BSLS_DEPRECATE_FEATURE_IS_SUPPORTED) && \
311 (defined(BB_DEPRECATE_ENABLE_ALL_DEPRECATIONS_FOR_TESTING) || \
312 defined(BSLS_DEPRECATE_FEATURE_ENABLE_ALL_DEPRECATIONS_FOR_TESTING))
313#define BSLS_DEPRECATE_FEATURE_ANNOTATION_IS_ACTIVE
314#else
315#undef BSLS_DEPRECATE_FEATURE_ANNOTATION_IS_ACTIVE
316#endif
317
318 // ====================================
319 // Implementation Details: Do *NOT* Use
320 // ====================================
321
322#ifndef BSLS_DEPRECATE_FEATURE_ANNOTATION_IS_ACTIVE
323 // Settings are off. We should be doing nothing.
324
325 #define BSLS_DEPRECATE_FEATURE_IMP(UOR, FEATURE, MESSAGE)
326 #define BSLS_DEPRECATE_FEATURE_HEADER_IMP(UOR, FEATURE, MESSAGE)
327#else
328 // ------------------------------------------------------------------------
329 // Utility macros
330
331 #define BSLS_DEPRECATE_FEATURE_HEADER_IMP_STRINGIFY(...) #__VA_ARGS__
332
333 // Lower level compiler macros are used as these macros may migrate out of
334 // bde in the future.
335 #if defined(__GNUC__) || defined(__clang__)
336 #define BSLS_DEPRECATE_FEATURE_HEADER_IMP_PRAGMA_DO(x) \
337 _Pragma (#x)
338 #else
339 #define BSLS_DEPRECATE_FEATURE_HEADER_IMP_PRAGMA_DO(x)
340 #endif
341
342 // ------------------------------------------------------------------------
343 // Main implementation macros
344
345 #define BSLS_DEPRECATE_FEATURE_HEADER_IMP_PRAGMA(MESSAGE) \
346 BSLS_DEPRECATE_FEATURE_HEADER_IMP_PRAGMA_DO(GCC warning MESSAGE)
347
348 #if defined(BB_DEPRECATE_ENABLE_JSON_MESSAGE) || \
349 defined(BSLS_DEPRECATE_FEATURE_ENABLE_JSON_MESSAGE)
350
351 // a. General c++ deprecation
352 #define BSLS_DEPRECATE_FEATURE_IMP(UOR, FEATURE, MESSAGE) \
353 [[deprecated("{\"library\": \"" UOR "\", \"feature\": \"" FEATURE \
354 "\", \"message\": \"" MESSAGE "\"}")]]
355
356 // b. Deprecated header
357 #define BSLS_DEPRECATE_FEATURE_HEADER_IMP(UOR, FEATURE, MESSAGE) \
358 BSLS_DEPRECATE_FEATURE_HEADER_IMP_PRAGMA( \
359 BSLS_DEPRECATE_FEATURE_HEADER_IMP_STRINGIFY( \
360 { \
361 "library": UOR, \
362 "feature": FEATURE, \
363 "message": MESSAGE \
364 }))
365 #else
366 // a. General c++ deprecation
367 #define BSLS_DEPRECATE_FEATURE_IMP(UOR, FEATURE, MESSAGE) \
368 [[deprecated(MESSAGE)]]
369
370 // b. Deprecated header
371 #define BSLS_DEPRECATE_FEATURE_HEADER_IMP(UOR, FEATURE, MESSAGE) \
372 BSLS_DEPRECATE_FEATURE_HEADER_IMP_PRAGMA(MESSAGE)
373 #endif // BB_DEPRECATE_ENABLE_JSON_MESSAGE
374#endif
375
376// If the number of arguments needs to be expanded, commit
377// abd14c70a7c9fb38d9bf3fe225eb0966cb036c9f contains a variadic implementation
378// similar to 'BSLIM_TESTUTIL_ASSERTV'.
379
380 // =================
381 // Annotation Macros
382 // =================
383
384// Usage: Macro for stating a general c++ deprecation (wraps c++'s
385// [[deprecated]]) ex. BSLS_DEPRECATE_FEATURE("my_uor", "my_feature", "Please
386// use y.h instead")
387#define BSLS_DEPRECATE_FEATURE(UOR, FEATURE, MESSAGE) \
388 BSLS_DEPRECATE_FEATURE_IMP(UOR, FEATURE, MESSAGE)
389
390// Usage: Macro for stating a deprecated header
391// ex. BSLS_DEPRECATE_FEATURE_HEADER("my_uor", "my_feature", "Please use y.h
392// instead")
393#define BSLS_DEPRECATE_FEATURE_HEADER(UOR, FEATURE, MESSAGE) \
394 BSLS_DEPRECATE_FEATURE_HEADER_IMP(UOR, FEATURE, MESSAGE)
395
396#endif // INCLUDED_BSLS_DEPRECATEFEATURE
397
398// ----------------------------------------------------------------------------
399// Copyright 2022 Bloomberg Finance L.P.
400//
401// Licensed under the Apache License, Version 2.0 (the "License");
402// you may not use this file except in compliance with the License.
403// You may obtain a copy of the License at
404//
405// http://www.apache.org/licenses/LICENSE-2.0
406//
407// Unless required by applicable law or agreed to in writing, software
408// distributed under the License is distributed on an "AS IS" BASIS,
409// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
410// See the License for the specific language governing permissions and
411// limitations under the License.
412// ----------------------------- END-OF-FILE ----------------------------------
413
414/** @} */
415/** @} */
416/** @} */