From 9590ab6787658a54728eac781fc87cc9429f585b Mon Sep 17 00:00:00 2001 From: Vladimir Still Date: Sun, 18 Aug 2024 19:58:06 +0200 Subject: [PATCH] Work around boost::format requiring deprecated allocate Signed-off-by: Vladimir Still --- backends/p4tools/common/lib/logging.h | 11 ++-- frontends/p4/typeChecking/typeCheckTypes.cpp | 6 +-- frontends/p4/typeChecking/typeConstraints.cpp | 2 +- frontends/p4/typeChecking/typeConstraints.h | 2 +- frontends/parsers/parserDriver.cpp | 5 +- lib/boost_format_compat.h | 53 +++++++++++++++++++ lib/bug_helper.h | 19 ++++--- lib/error_helper.h | 31 ++++++----- lib/error_reporter.h | 9 ++-- lib/exceptions.h | 2 +- 10 files changed, 94 insertions(+), 46 deletions(-) create mode 100644 lib/boost_format_compat.h diff --git a/backends/p4tools/common/lib/logging.h b/backends/p4tools/common/lib/logging.h index 5e6dde01d49..2ff39db1aee 100644 --- a/backends/p4tools/common/lib/logging.h +++ b/backends/p4tools/common/lib/logging.h @@ -6,18 +6,17 @@ #include #include -#include - +#include "lib/boost_format_compat.h" #include "lib/log.h" namespace P4::P4Tools { /// Helper function for @printFeature -inline std::string logHelper(boost::format &f) { return f.str(); } +inline BoostFormatCompat &logHelper(BoostFormatCompat &f) { return f; } /// Helper function for @printFeature template -std::string logHelper(boost::format &f, T &&t, Args &&...args) { +BoostFormatCompat &logHelper(BoostFormatCompat &f, T &&t, Args &&...args) { return logHelper(f % std::forward(t), std::forward(args)...); } @@ -32,8 +31,8 @@ void printFeature(const std::string &label, int level, const std::string &fmt, return; } - boost::format f(fmt); - LOG_FEATURE(label.c_str(), level, logHelper(f, std::forward(args)...)); + BoostFormatCompat f(fmt.c_str()); + LOG_FEATURE(label.c_str(), level, logHelper(f, std::forward(args)...).str()); } /// Helper functions that prints strings associated with basic tool information. diff --git a/frontends/p4/typeChecking/typeCheckTypes.cpp b/frontends/p4/typeChecking/typeCheckTypes.cpp index c2ef36c7148..961ea6ec18e 100644 --- a/frontends/p4/typeChecking/typeCheckTypes.cpp +++ b/frontends/p4/typeChecking/typeCheckTypes.cpp @@ -331,13 +331,13 @@ static bool checkEnumValueInitializer(const IR::Type_Bits *type, const IR::Expre std::string extraMsg; if (!type->isSigned && constant->value < low) { extraMsg = - str(boost::format( + str(BoostFormatCompat( "the value %1% is negative, but the underlying type %2% is unsigned") % constant->value % type->toString()); } else { extraMsg = - str(boost::format("the value %1% requires %2% bits but the underlying " - "%3% type %4% only contains %5% bits") % + str(BoostFormatCompat("the value %1% requires %2% bits but the underlying " + "%3% type %4% only contains %5% bits") % constant->value % required % (type->isSigned ? "signed" : "unsigned") % type->toString() % type->size); } diff --git a/frontends/p4/typeChecking/typeConstraints.cpp b/frontends/p4/typeChecking/typeConstraints.cpp index adb0f7ad916..2cffa2b9a17 100644 --- a/frontends/p4/typeChecking/typeConstraints.cpp +++ b/frontends/p4/typeChecking/typeConstraints.cpp @@ -124,7 +124,7 @@ std::string TypeConstraint::localError(Explain *explainer) const { if (errFormat.isNullOrEmpty()) return ""; std::string message, explanation; - boost::format fmt = boost::format(errFormat); + BoostFormatCompat fmt(errFormat); switch (errArguments.size()) { case 0: message = boost::str(fmt); diff --git a/frontends/p4/typeChecking/typeConstraints.h b/frontends/p4/typeChecking/typeConstraints.h index 6cda85f4ad0..fcc309c7ede 100644 --- a/frontends/p4/typeChecking/typeConstraints.h +++ b/frontends/p4/typeChecking/typeConstraints.h @@ -92,7 +92,7 @@ class TypeConstraint : public IHasDbPrint, public ICastable { /// composed in reverse order, from bottom to top. The top of the stack /// has no 'derivedFrom' field, and it contains the actual source /// position where the analysis started. - boost::format fmt(format); + BoostFormatCompat fmt(format); return reportErrorImpl(subst, " ---- Actual error:\n" + ::P4::error_helper(fmt, std::forward(args)...).toString()); diff --git a/frontends/parsers/parserDriver.cpp b/frontends/parsers/parserDriver.cpp index 96e9d3a2a93..1df6d8b7df3 100644 --- a/frontends/parsers/parserDriver.cpp +++ b/frontends/parsers/parserDriver.cpp @@ -6,8 +6,6 @@ #include #include -#include - #include "frontends/common/constantFolding.h" #include "frontends/common/options.h" #include "frontends/parsers/p4/p4AnnotationLexer.hpp" @@ -15,6 +13,7 @@ #include "frontends/parsers/p4/p4parser.hpp" #include "frontends/parsers/v1/v1lexer.hpp" #include "frontends/parsers/v1/v1parser.hpp" +#include "lib/boost_format_compat.h" #include "lib/error.h" #ifdef HAVE_LIBBOOST_IOSTREAMS @@ -108,7 +107,7 @@ void AbstractParserDriver::onParseError(const Util::SourceInfo &location, auto &context = BaseCompileContext::get(); if (message == unexpectedIdentifierError) { context.errorReporter().parser_error( - location, boost::format("%s \"%s\"") % unexpectedIdentifierError % lastIdentifier); + location, BoostFormatCompat("%s \"%s\"") % unexpectedIdentifierError % lastIdentifier); } else { context.errorReporter().parser_error(location, message); } diff --git a/lib/boost_format_compat.h b/lib/boost_format_compat.h new file mode 100644 index 00000000000..dbc5d46c17e --- /dev/null +++ b/lib/boost_format_compat.h @@ -0,0 +1,53 @@ +/* +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. +*/ + +#ifndef LIB_BOOST_FORMAT_COMPAT_H_ +#define LIB_BOOST_FORMAT_COMPAT_H_ + +#include + +namespace P4 { + +/// Allocator wrapper that adds the overload removed in C++20 for the sake of Boost. +template +struct BoostCompatAllocator : std::allocator { + /// Inherit constructors. + using std::allocator::allocator; + + BoostCompatAllocator() = default; + /// Explictly make it possible to construct our allocator from std::allocator. + /// Some parts of libstdc++ 9 require that for some reason. + BoostCompatAllocator(const std::allocator &other) + : std::allocator(other) {} // NOLINT(runtime/explicit) + BoostCompatAllocator(std::allocator &&other) + : std::allocator(std::move(other)) {} // NOLINT(runtime/explicit) + + /// This one was removed in C++20, but boost::format < 1.74 needs it. + T *allocate(typename std::allocator::size_type n, const void *) { return allocate(n); } + + /// Explicitly wrap the other overload (instead of using using std::allocator::allocate. + /// The latter does not work with GCC 9. + T *allocate(typename std::allocator::size_type n) { return std::allocator::allocate(n); } +}; + +/// Boost < 1.74 is not compatible with C++20 as it expect deprecated +/// allocator::allocate(size_type, void*) to exist. To work around that, we use a simple wrapper +/// over std::allocator that adds this overload back. All uses of boost::format in P4C should use +// this type instead. +using BoostFormatCompat = + boost::basic_format, BoostCompatAllocator>; + +} // namespace P4 + +#endif // LIB_BOOST_FORMAT_COMPAT_H_ diff --git a/lib/bug_helper.h b/lib/bug_helper.h index c8f52eec75e..bd2cdee3b46 100644 --- a/lib/bug_helper.h +++ b/lib/bug_helper.h @@ -23,9 +23,8 @@ limitations under the License. #include #include -#include - #include "absl/strings/str_cat.h" +#include "boost_format_compat.h" #include "cstring.h" #include "source_file.h" #include "stringify.h" @@ -60,27 +59,27 @@ std::pair maybeAddSourceInfo(const T &t, std::str return {"", ""}; } -static inline std::string bug_helper(boost::format &f, std::string_view position, +static inline std::string bug_helper(BoostFormatCompat &f, std::string_view position, std::string_view tail) { return absl::StrCat(position, position.empty() ? "" : ": ", boost::str(f), "\n", tail); } template -auto bug_helper(boost::format &f, std::string_view position, std::string_view tail, const T *t, +auto bug_helper(BoostFormatCompat &f, std::string_view position, std::string_view tail, const T *t, Args &&...args); template -auto bug_helper(boost::format &f, std::string_view position, std::string_view tail, const T &t, +auto bug_helper(BoostFormatCompat &f, std::string_view position, std::string_view tail, const T &t, Args &&...args) -> std::enable_if_t, std::string>; template -std::string bug_helper(boost::format &f, std::string_view position, std::string_view tail, +std::string bug_helper(BoostFormatCompat &f, std::string_view position, std::string_view tail, const char *t, Args &&...args) { return bug_helper(f % t, position, tail, std::forward(args)...); } template -std::string bug_helper(boost::format &f, std::string_view position, std::string_view tail, +std::string bug_helper(BoostFormatCompat &f, std::string_view position, std::string_view tail, const Util::SourceInfo &info, Args &&...args) { auto [outPos, outTail] = detail::getPositionTail(info, position, tail); return bug_helper(f % "", outPos, outTail, std::forward(args)...); @@ -105,7 +104,7 @@ std::ostream &operator<<(std::ostream &os, const DbprintDispatchPtr &dispatch } template -auto bug_helper(boost::format &f, std::string_view position, std::string_view tail, const T *t, +auto bug_helper(BoostFormatCompat &f, std::string_view position, std::string_view tail, const T *t, Args &&...args) { if (t == nullptr) return bug_helper(f, position, tail, std::forward(args)...); @@ -132,7 +131,7 @@ std::ostream &operator<<(std::ostream &os, const DbprintDispatchRef &dispatch } template -auto bug_helper(boost::format &f, std::string_view position, std::string_view tail, const T &t, +auto bug_helper(BoostFormatCompat &f, std::string_view position, std::string_view tail, const T &t, Args &&...args) -> std::enable_if_t, std::string> { auto [outPos, outTail] = maybeAddSourceInfo(t, position, tail); return bug_helper(f % DbprintDispatchRef{t}, outPos, outTail, std::forward(args)...); @@ -141,7 +140,7 @@ auto bug_helper(boost::format &f, std::string_view position, std::string_view ta // Most direct invocations of bug_helper usually only reduce arguments template -std::string bug_helper(boost::format &f, std::string_view position, std::string_view tail, +std::string bug_helper(BoostFormatCompat &f, std::string_view position, std::string_view tail, Args &&...args) { return detail::bug_helper(f, position, tail, std::forward(args)...); } diff --git a/lib/error_helper.h b/lib/error_helper.h index bedf17f09e7..cfe354fe432 100644 --- a/lib/error_helper.h +++ b/lib/error_helper.h @@ -18,8 +18,7 @@ limitations under the License. #include -#include - +#include "lib/boost_format_compat.h" #include "lib/error_message.h" #include "lib/source_file.h" #include "lib/stringify.h" @@ -29,26 +28,26 @@ namespace priv { // All these methods return std::string because this is the native format of boost::format // Position is printed at the beginning. -static inline ErrorMessage error_helper(boost::format &f, ErrorMessage out) { +static inline ErrorMessage error_helper(BoostFormatCompat &f, ErrorMessage out) { out.message = boost::str(f); return out; } template -auto error_helper(boost::format &f, ErrorMessage out, const char *t, Args &&...args) { +auto error_helper(BoostFormatCompat &f, ErrorMessage out, const char *t, Args &&...args) { return error_helper(f % t, out, std::forward(args)...); } template -auto error_helper(boost::format &f, ErrorMessage out, const T &t, - Args &&...args) -> std::enable_if_t, ErrorMessage>; +auto error_helper(BoostFormatCompat &f, ErrorMessage out, const T &t, Args &&...args) + -> std::enable_if_t, ErrorMessage>; template -auto error_helper(boost::format &f, ErrorMessage out, const T &t, Args &&...args) +auto error_helper(BoostFormatCompat &f, ErrorMessage out, const T &t, Args &&...args) -> std::enable_if_t && !std::is_pointer_v, ErrorMessage>; template -auto error_helper(boost::format &f, ErrorMessage out, const T *t, Args &&...args) { +auto error_helper(BoostFormatCompat &f, ErrorMessage out, const T *t, Args &&...args) { // Contrary to bug_helper we do not want to show raw pointers to users in // ordinary error messages. Therefore we explicitly delegate to // reference-arg implementation here. @@ -56,7 +55,7 @@ auto error_helper(boost::format &f, ErrorMessage out, const T *t, Args &&...args } template -ErrorMessage error_helper(boost::format &f, ErrorMessage out, const Util::SourceInfo &info, +ErrorMessage error_helper(BoostFormatCompat &f, ErrorMessage out, const Util::SourceInfo &info, Args &&...args) { if (info.isValid()) out.locations.push_back(info); return error_helper(f % "", std::move(out), std::forward(args)...); @@ -71,15 +70,15 @@ void maybeAddSourceInfo(ErrorMessage &out, const T &t) { } template -auto error_helper(boost::format &f, ErrorMessage out, const T &t, Args &&...args) +auto error_helper(BoostFormatCompat &f, ErrorMessage out, const T &t, Args &&...args) -> std::enable_if_t && !std::is_pointer_v, ErrorMessage> { maybeAddSourceInfo(out, t); return error_helper(f % t, std::move(out), std::forward(args)...); } template -auto error_helper(boost::format &f, ErrorMessage out, const T &t, - Args &&...args) -> std::enable_if_t, ErrorMessage> { +auto error_helper(BoostFormatCompat &f, ErrorMessage out, const T &t, Args &&...args) + -> std::enable_if_t, ErrorMessage> { maybeAddSourceInfo(out, t); return error_helper(f % t.toString(), std::move(out), std::forward(args)...); } @@ -88,21 +87,21 @@ auto error_helper(boost::format &f, ErrorMessage out, const T &t, // Most direct invocations of error_helper usually only reduce arguments template -ErrorMessage error_helper(boost::format &f, Args &&...args) { +ErrorMessage error_helper(BoostFormatCompat &f, Args &&...args) { ErrorMessage msg; return priv::error_helper(f, msg, std::forward(args)...); } // Invoked from ErrorReporter template -ErrorMessage error_helper(boost::format &f, ErrorMessage msg, Args &&...args) { +ErrorMessage error_helper(BoostFormatCompat &f, ErrorMessage msg, Args &&...args) { return priv::error_helper(f, std::move(msg), std::forward(args)...); } // This overload exists for backwards compatibility template -ErrorMessage error_helper(boost::format &f, const std::string &prefix, const Util::SourceInfo &info, - const std::string &suffix, Args &&...args) { +ErrorMessage error_helper(BoostFormatCompat &f, const std::string &prefix, + const Util::SourceInfo &info, const std::string &suffix, Args &&...args) { return priv::error_helper(f, ErrorMessage(prefix, info, suffix), std::forward(args)...); } diff --git a/lib/error_reporter.h b/lib/error_reporter.h index b0005c4b8cb..9b8962ea0d1 100644 --- a/lib/error_reporter.h +++ b/lib/error_reporter.h @@ -23,9 +23,8 @@ limitations under the License. #include #include -#include - #include "absl/strings/str_format.h" +#include "boost_format_compat.h" #include "bug_helper.h" #include "error_catalog.h" #include "error_helper.h" @@ -96,7 +95,7 @@ class ErrorReporter { // error message for a bug template std::string bug_message(const char *format, Args &&...args) { - boost::format fmt(format); + BoostFormatCompat fmt(format); // FIXME: This will implicitly take location of the first argument having // SourceInfo. Not sure if this always desireable or not. return ::P4::bug_helper(fmt, "", "", std::forward(args)...); @@ -104,7 +103,7 @@ class ErrorReporter { template std::string format_message(const char *format, Args &&...args) { - boost::format fmt(format); + BoostFormatCompat fmt(format); return ::P4::error_helper(fmt, std::forward(args)...).toString(); } @@ -157,7 +156,7 @@ class ErrorReporter { msgType = ErrorMessage::MessageType::Error; } - boost::format fmt(format); + BoostFormatCompat fmt(format); ErrorMessage msg(msgType, diagnosticName ? diagnosticName : "", suffix); msg = ::P4::error_helper(fmt, msg, std::forward(args)...); emit_message(msg); diff --git a/lib/exceptions.h b/lib/exceptions.h index 0f62fde0932..fc59df0a1e6 100644 --- a/lib/exceptions.h +++ b/lib/exceptions.h @@ -76,7 +76,7 @@ class P4CExceptionBase : public std::exception { template explicit P4CExceptionBase(const char *format, Args &&...args) { traceCreation(); - boost::format fmt(format); + BoostFormatCompat fmt(format); // FIXME: This will implicitly take location of the first argument having // SourceInfo. Not sure if this always desireable or not. message = ::P4::bug_helper(fmt, "", "", std::forward(args)...);