Skip to content

Commit

Permalink
Work around boost::format requiring deprecated allocate
Browse files Browse the repository at this point in the history
Signed-off-by: Vladimir Still <git@vstill.eu>
  • Loading branch information
vlstill committed Aug 18, 2024
1 parent 8a59817 commit 4010ffb
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 46 deletions.
11 changes: 5 additions & 6 deletions backends/p4tools/common/lib/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@
#include <string>
#include <utility>

#include <boost/format.hpp>

#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 <class T, class... Args>
std::string logHelper(boost::format &f, T &&t, Args &&...args) {
BoostFormatCompat &logHelper(BoostFormatCompat &f, T &&t, Args &&...args) {
return logHelper(f % std::forward<T>(t), std::forward<Args>(args)...);
}

Expand All @@ -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<Arguments>(args)...));
BoostFormatCompat f(fmt.c_str());
LOG_FEATURE(label.c_str(), level, logHelper(f, std::forward<Arguments>(args)...).str());
}

/// Helper functions that prints strings associated with basic tool information.
Expand Down
6 changes: 3 additions & 3 deletions frontends/p4/typeChecking/typeCheckTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/typeChecking/typeConstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/typeChecking/typeConstraints.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>(args)...).toString());
Expand Down
5 changes: 2 additions & 3 deletions frontends/parsers/parserDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
#include <sstream>
#include <string_view>

#include <boost/format.hpp>

#include "frontends/common/constantFolding.h"
#include "frontends/common/options.h"
#include "frontends/parsers/p4/p4AnnotationLexer.hpp"
#include "frontends/parsers/p4/p4lexer.hpp"
#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
Expand Down Expand Up @@ -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);
}
Expand Down
50 changes: 50 additions & 0 deletions lib/boost_format_compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
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 <boost/format.hpp>

namespace P4 {

/// Allocator wrapper that adds the overload removed in C++20 for the sake of Boost.
template <typename T>
struct BoostCompatAllocator : std::allocator<T> {
/// Inherit constructors.
using std::allocator<T>::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<T> &other) : std::allocator<T>(other) {}
BoostCompatAllocator(std::allocator<T> &&other) : std::allocator<T>(std::move(other)) {}

/// Make sure the base class'es allocate is visible.
using std::allocator<T>::allocate;

/// This one was removed in C++20, but boost::format < 1.74 needs it.
T *allocate(typename std::allocator<T>::size_type n, const void *) { return 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<char, std::char_traits<char>, BoostCompatAllocator<char>>;

} // namespace P4

#endif // LIB_BOOST_FORMAT_COMPAT_H_
19 changes: 9 additions & 10 deletions lib/bug_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ limitations under the License.
#include <string_view>
#include <utility>

#include <boost/format.hpp>

#include "absl/strings/str_cat.h"
#include "boost_format_compat.h"
#include "cstring.h"
#include "source_file.h"
#include "stringify.h"
Expand Down Expand Up @@ -60,27 +59,27 @@ std::pair<std::string_view, std::string> 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 <typename T, class... Args>
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 <typename T, class... Args>
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::is_pointer_v<T>, std::string>;

template <class... Args>
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>(args)...);
}

template <class... Args>
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>(args)...);
Expand All @@ -105,7 +104,7 @@ std::ostream &operator<<(std::ostream &os, const DbprintDispatchPtr<T> &dispatch
}

template <typename T, class... Args>
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>(args)...);

Expand All @@ -132,7 +131,7 @@ std::ostream &operator<<(std::ostream &os, const DbprintDispatchRef<T> &dispatch
}

template <typename T, class... Args>
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::is_pointer_v<T>, std::string> {
auto [outPos, outTail] = maybeAddSourceInfo(t, position, tail);
return bug_helper(f % DbprintDispatchRef<T>{t}, outPos, outTail, std::forward<Args>(args)...);
Expand All @@ -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 <class... Args>
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>(args)...);
}
Expand Down
32 changes: 16 additions & 16 deletions lib/error_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ limitations under the License.
#ifndef LIB_ERROR_HELPER_H_
#define LIB_ERROR_HELPER_H_

#include <type_traits>
#include <lib/boost_format_compat.h>

#include <boost/format.hpp>
#include <type_traits>

#include "lib/error_message.h"
#include "lib/source_file.h"
Expand All @@ -29,34 +29,34 @@ 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 <class... Args>
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>(args)...);
}

template <typename T, class... Args>
auto error_helper(boost::format &f, ErrorMessage out, const T &t,
Args &&...args) -> std::enable_if_t<Util::has_toString_v<T>, ErrorMessage>;
auto error_helper(BoostFormatCompat &f, ErrorMessage out, const T &t, Args &&...args)
-> std::enable_if_t<Util::has_toString_v<T>, ErrorMessage>;

template <typename T, class... Args>
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<!Util::has_toString_v<T> && !std::is_pointer_v<T>, ErrorMessage>;

template <typename T, class... Args>
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.
return error_helper(f, out, *t, std::forward<Args>(args)...);
}

template <class... Args>
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>(args)...);
Expand All @@ -71,15 +71,15 @@ void maybeAddSourceInfo(ErrorMessage &out, const T &t) {
}

template <typename T, class... Args>
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<!Util::has_toString_v<T> && !std::is_pointer_v<T>, ErrorMessage> {
maybeAddSourceInfo(out, t);
return error_helper(f % t, std::move(out), std::forward<Args>(args)...);
}

template <typename T, class... Args>
auto error_helper(boost::format &f, ErrorMessage out, const T &t,
Args &&...args) -> std::enable_if_t<Util::has_toString_v<T>, ErrorMessage> {
auto error_helper(BoostFormatCompat &f, ErrorMessage out, const T &t, Args &&...args)
-> std::enable_if_t<Util::has_toString_v<T>, ErrorMessage> {
maybeAddSourceInfo(out, t);
return error_helper(f % t.toString(), std::move(out), std::forward<Args>(args)...);
}
Expand All @@ -88,21 +88,21 @@ auto error_helper(boost::format &f, ErrorMessage out, const T &t,

// Most direct invocations of error_helper usually only reduce arguments
template <class... Args>
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>(args)...);
}

// Invoked from ErrorReporter
template <class... Args>
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>(args)...);
}

// This overload exists for backwards compatibility
template <class... Args>
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>(args)...);
}

Expand Down
9 changes: 4 additions & 5 deletions lib/error_reporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ limitations under the License.
#include <type_traits>
#include <unordered_map>

#include <boost/format.hpp>

#include "absl/strings/str_format.h"
#include "boost_format_compat.h"
#include "bug_helper.h"
#include "error_catalog.h"
#include "error_helper.h"
Expand Down Expand Up @@ -96,15 +95,15 @@ class ErrorReporter {
// error message for a bug
template <typename... Args>
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>(args)...);
}

template <typename... Args>
std::string format_message(const char *format, Args &&...args) {
boost::format fmt(format);
BoostFormatCompat fmt(format);
return ::P4::error_helper(fmt, std::forward<Args>(args)...).toString();
}

Expand Down Expand Up @@ -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>(args)...);
emit_message(msg);
Expand Down
2 changes: 1 addition & 1 deletion lib/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class P4CExceptionBase : public std::exception {
template <typename... Args>
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>(args)...);
Expand Down

0 comments on commit 4010ffb

Please sign in to comment.