From 43b026f3f9690bb78b357a062133858931632932 Mon Sep 17 00:00:00 2001 From: "Daniel R. Carvalho" Date: Sat, 8 May 2021 08:38:44 -0300 Subject: [PATCH] base: Add macros to deprecate namespaces and classes The GEM5_DEPRECATED_NAMESPACE macro temporarily declares a namespace with the deprecated name that prints a warning message when used. It also make sure that when the old namespace name is used the new name is referenced. The GEM5_DEPRECATED_CLASS macro deprecates classes that were renamed, or moved to different namespaces. Attributes in namespaces are an issue, though. - Clang only allows from version 6 on, and only when using C++17. - GCC has a bug before version 10 where the deprecated attribute was not properly recognized in namespaces: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79817 Possible solutions for GCC < 10: 1) \#define GEM5_DEPRECATED_NAMESPACE() \ namespace gem5 { namespace deprecated { \ auto namespace_##old_namespace = [](){ \ GEM5_DEPRECATED("Please use the new namespace: '" \ \#new_namespace "'") \ int old_namespace; \ return old_namespace; \ }; \ }} \ namespace new_namespace {} \ namespace old_namespace { \ using namespace new_namespace; \ } Add the above macro to all headers that previously declared the deprecated namespace to trigger a warning. This is extremely inconvenient because every file that includes that header will trigger the deprecation warning, so the compilation output gets VERY clogged. 2) Similar to 1), but do not use the temporary variable on declaration. This would require using the variable somewhere else, like a respective .c file. This is not always possible, so we could resort to adding a special file (e.g., base/deprecated_elements.cc) containing all uses of the deprecated temporary variables. 3) \#define GEM5_DEPRECATED_NAMESPACE(old_ns, new_ns) \ namespace old_ns = new_ns; Similar to 3), but simply declare an alias in the header files (see above macro) to maintain backwards compatibility. Then use the special file to declare all deprecation messages. 4) Rely on release notes / e-mail to the mailing list to inform that those are deprecated. We have selected option 4 for these problematic instances. Checking if namespace deprecation is possible is done through scons. Jira issues: https://gem5.atlassian.net/browse/GEM5-975 https://gem5.atlassian.net/browse/GEM5-991 Change-Id: Ide234f6a8707d88a869fa843bf8c61ca7714e4f3 Signed-off-by: Daniel R. Carvalho Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/45246 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/base/SConsopts | 12 +++++++++++- src/base/compiler.hh | 28 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/base/SConsopts b/src/base/SConsopts index 9b301c32f3..ea11bd4de0 100644 --- a/src/base/SConsopts +++ b/src/base/SConsopts @@ -56,10 +56,20 @@ with gem5_scons.Configure(main) as conf: # alternative stacks. conf.env['HAVE_VALGRIND'] = conf.CheckCHeader('valgrind/valgrind.h') + conf.env['HAVE_DEPRECATED_NAMESPACE'] = conf.TryCompile(''' + int main() {return 0;} + namespace [[gnu::deprecated("Test namespace deprecation")]] + test_deprecated_namespace {} + ''', '.cc') + if not conf.env['HAVE_DEPRECATED_NAMESPACE']: + warning("Deprecated namespaces are not supported by this compiler.\n" + "Please make sure to check the mailing list for deprecation " + "announcements.") sticky_vars.Add(BoolVariable('USE_POSIX_CLOCK', 'Use POSIX Clocks', have_posix_clock)) export_vars.extend([ - 'HAVE_FENV', 'HAVE_PNG', 'USE_POSIX_CLOCK', 'HAVE_VALGRIND']) + 'HAVE_FENV', 'HAVE_PNG', 'USE_POSIX_CLOCK', 'HAVE_VALGRIND', + 'HAVE_DEPRECATED_NAMESPACE']) diff --git a/src/base/compiler.hh b/src/base/compiler.hh index 17124bebe4..8fd38080fb 100644 --- a/src/base/compiler.hh +++ b/src/base/compiler.hh @@ -43,6 +43,8 @@ #include +#include "config/have_deprecated_namespace.hh" + // http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html @@ -138,6 +140,32 @@ # define GEM5_DEPRECATED_MACRO_STMT(name, definition, message) \ do {{definition;} GEM5_DEPRECATED_MACRO(name, {}, message);} while (0) +// To mark a class as deprecated in favor of a new name, add a respective +// instance of this macro to the file that used to declare the old name. +// This macro should be used *after* the new class has been defined. +# define GEM5_DEPRECATED_CLASS(old_class, new_class) \ + using old_class \ + GEM5_DEPRECATED("Please use the new class name: '" #new_class "'") = \ + new_class + +// These macros should be used when namespaces are deprecated in favor of +// a new name. They should be used wherever the namespace is declared. +// Namespace deprecation is broken for GNU < 10 [1], so there is no +// deprecation warning in that case. Clang only supports it from C++17 on. +// [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79817 +# if HAVE_DEPRECATED_NAMESPACE +# define GEM5_DEPRECATED_NAMESPACE(old_namespace, new_namespace) \ + namespace new_namespace {} \ + namespace GEM5_DEPRECATED("Please use the new namespace: '" \ + #new_namespace "'") old_namespace { \ + using namespace new_namespace; \ + } +# else +# define GEM5_DEPRECATED_NAMESPACE(old_namespace, new_namespace) \ + namespace new_namespace {} \ + namespace old_namespace = new_namespace +# endif + // Evaluate an expanded parameter pack in order. Multiple arguments can be // passed in which be evaluated in order relative to each other as a group. // The argument(s) must include a parameter pack to expand. This works because