From 02dc3a9507043c975c24e41108d30423b1295ea7 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 19 Dec 2017 08:42:24 +0100 Subject: [PATCH 1/3] Workaround for GCC bug 61321 --- lib/base/functionwrapper.hpp | 101 +++++++++++++++++++++++----------- lib/config/vmops.hpp | 2 +- lib/icinga/macroprocessor.cpp | 51 +++++++---------- lib/icinga/macroprocessor.hpp | 6 -- 4 files changed, 91 insertions(+), 69 deletions(-) diff --git a/lib/base/functionwrapper.hpp b/lib/base/functionwrapper.hpp index a8cbce913..2ee22d9b2 100644 --- a/lib/base/functionwrapper.hpp +++ b/lib/base/functionwrapper.hpp @@ -23,6 +23,9 @@ #include "base/i2-base.hpp" #include "base/value.hpp" #include +#include +#include +#include #include #include @@ -31,7 +34,14 @@ using namespace std::placeholders; namespace icinga { -inline std::function&)> WrapFunction(const std::function&)>& function) +template +typename std::enable_if< + std::is_class::value && + std::is_same::type, Value>::value && + std::is_same, 1>::type, const std::vector&>::value && + boost::function_types::function_arity::value == 2, + std::function&)>>::type +WrapFunction(FuncType function) { return function; } @@ -43,12 +53,11 @@ inline std::function&)> WrapFunction(void (*func return Empty; }; } + template std::function&)> WrapFunction(Return (*function)(const std::vector&)) { - return [function](const std::vector& arguments) { - return static_cast(function(arguments)); - }; + return std::bind(function, _1); } template @@ -69,52 +78,51 @@ struct build_indices<0> { template using BuildIndices = typename build_indices::type; -struct unpack_caller +struct UnpackCaller { private: template - auto call(FuncType f, const std::vector& args, indices) -> decltype(f(args[I]...)) + auto Invoke(FuncType f, const std::vector& args, indices) -> decltype(f(args[I]...)) { return f(args[I]...); } public: - template - auto operator () (FuncType f, const std::vector& args) - -> decltype(call(f, args, BuildIndices::type>::value>{})) + template + auto operator() (FuncType f, const std::vector& args) + -> decltype(Invoke(f, args, BuildIndices{})) { - return call(f, args, BuildIndices::type>::value>{}); + return Invoke(f, args, BuildIndices{}); } }; -enum class enabler_t {}; - -template -using EnableIf = typename std::enable_if::type; - -template -std::function&)> WrapFunction(FuncType function, - EnableIf())), void>::value>* = 0) +template +struct FunctionWrapper { - return [function](const std::vector& arguments) { - constexpr int arity = boost::function_types::function_arity::type>::value; + static Value Invoke(FuncType function, const std::vector& arguments) + { + return UnpackCaller().operator()(function, arguments); + } +}; - if (arguments.size() < arity) - BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); - else if (arguments.size() > arity) - BOOST_THROW_EXCEPTION(std::invalid_argument("Too many arguments for function.")); - - unpack_caller()(function, arguments); +template +struct FunctionWrapper +{ + static Value Invoke(FuncType function, const std::vector& arguments) + { + UnpackCaller().operator()(function, arguments); return Empty; - }; -} + } +}; template -std::function&)> WrapFunction(FuncType function, - EnableIf())), void>::value>* = 0) +typename std::enable_if< + std::is_function::type>::value && !std::is_same&)>::value, + std::function&)>>::type +WrapFunction(FuncType function) { return [function](const std::vector& arguments) { - constexpr int arity = boost::function_types::function_arity::type>::value; + constexpr size_t arity = boost::function_types::function_arity::type>::value; if (arity > 0) { if (arguments.size() < arity) @@ -123,7 +131,36 @@ std::function&)> WrapFunction(FuncType function, BOOST_THROW_EXCEPTION(std::invalid_argument("Too many arguments for function.")); } - return unpack_caller()(function, arguments); + using ReturnType = decltype(UnpackCaller().operator()(*static_cast(nullptr), std::vector())); + + return FunctionWrapper::Invoke(function, arguments); + }; +} + +template +typename std::enable_if< + std::is_class::value && + !(std::is_same::type, Value>::value && + std::is_same, 1>::type, const std::vector&>::value && + boost::function_types::function_arity::value == 2), + std::function&)>>::type +WrapFunction(FuncType function) +{ + using FuncTypeInvoker = decltype(&FuncType::operator()); + + return [function](const std::vector& arguments) { + constexpr size_t arity = boost::function_types::function_arity::value - 1; + + if (arity > 0) { + if (arguments.size() < arity) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + else if (arguments.size() > arity) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too many arguments for function.")); + } + + using ReturnType = decltype(UnpackCaller().operator()(*static_cast(nullptr), std::vector())); + + return FunctionWrapper::Invoke(function, arguments); }; } diff --git a/lib/config/vmops.hpp b/lib/config/vmops.hpp index 97c5d6358..323ba51ee 100644 --- a/lib/config/vmops.hpp +++ b/lib/config/vmops.hpp @@ -113,7 +113,7 @@ public: { auto evaluatedClosedVars = EvaluateClosedVars(frame, closedVars); - auto wrapper = [argNames, evaluatedClosedVars, expression](const std::vector& arguments) { + auto wrapper = [argNames, evaluatedClosedVars, expression](const std::vector& arguments) -> Value { if (arguments.size() < argNames.size()) BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function")); diff --git a/lib/icinga/macroprocessor.cpp b/lib/icinga/macroprocessor.cpp index e3d81202f..9789313f7 100644 --- a/lib/icinga/macroprocessor.cpp +++ b/lib/icinga/macroprocessor.cpp @@ -180,30 +180,6 @@ bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resol return false; } -Value MacroProcessor::InternalResolveMacrosShim(const std::vector& args, const ResolverList& resolvers, - const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros, - bool useResolvedMacros, int recursionLevel) -{ - if (args.size() < 1) - BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function")); - - String missingMacro; - - return MacroProcessor::InternalResolveMacros(args[0], resolvers, cr, &missingMacro, escapeFn, - resolvedMacros, useResolvedMacros, recursionLevel); -} - -Value MacroProcessor::InternalResolveArgumentsShim(const std::vector& args, const ResolverList& resolvers, - const CheckResult::Ptr& cr, const Dictionary::Ptr& resolvedMacros, - bool useResolvedMacros, int recursionLevel) -{ - if (args.size() < 2) - BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function")); - - return MacroProcessor::ResolveArguments(args[0], args[1], resolvers, cr, - resolvedMacros, useResolvedMacros, recursionLevel); -} - Value MacroProcessor::EvaluateFunction(const Function::Ptr& func, const ResolverList& resolvers, const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel) @@ -214,12 +190,27 @@ Value MacroProcessor::EvaluateFunction(const Function::Ptr& func, const Resolver resolvers_this->Set(resolver.first, resolver.second); } - resolvers_this->Set("macro", new Function("macro (temporary)", std::bind(&MacroProcessor::InternalResolveMacrosShim, - _1, std::cref(resolvers), cr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros, - recursionLevel + 1), { "str" })); - resolvers_this->Set("resolve_arguments", new Function("resolve_arguments (temporary)", std::bind(&MacroProcessor::InternalResolveArgumentsShim, - _1, std::cref(resolvers), cr, resolvedMacros, useResolvedMacros, - recursionLevel + 1))); + auto internalResolveMacrosShim = [resolvers, cr, resolvedMacros, useResolvedMacros, recursionLevel](const std::vector& args) { + if (args.size() < 1) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function")); + + String missingMacro; + + return MacroProcessor::InternalResolveMacros(args[0], resolvers, cr, &missingMacro, MacroProcessor::EscapeCallback(), + resolvedMacros, useResolvedMacros, recursionLevel); + }; + + resolvers_this->Set("macro", new Function("macro (temporary)", internalResolveMacrosShim, { "str" })); + + auto internalResolveArgumentsShim = [resolvers, cr, resolvedMacros, useResolvedMacros, recursionLevel](const std::vector& args) { + if (args.size() < 2) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function")); + + return MacroProcessor::ResolveArguments(args[0], args[1], resolvers, cr, + resolvedMacros, useResolvedMacros, recursionLevel + 1); + }; + + resolvers_this->Set("resolve_arguments", new Function("resolve_arguments (temporary)", internalResolveArgumentsShim, { "command", "args" })); return func->InvokeThis(resolvers_this); } diff --git a/lib/icinga/macroprocessor.hpp b/lib/icinga/macroprocessor.hpp index 1b2c015da..8924162ae 100644 --- a/lib/icinga/macroprocessor.hpp +++ b/lib/icinga/macroprocessor.hpp @@ -63,12 +63,6 @@ private: String *missingMacro, const EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel = 0); - static Value InternalResolveMacrosShim(const std::vector& args, const ResolverList& resolvers, - const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn, - const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel); - static Value InternalResolveArgumentsShim(const std::vector& args, const ResolverList& resolvers, - const CheckResult::Ptr& cr, const Dictionary::Ptr& resolvedMacros, - bool useResolvedMacros, int recursionLevel); static Value EvaluateFunction(const Function::Ptr& func, const ResolverList& resolvers, const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel); From b63caaa756ebca7e15a256c534650b68fbd4a046 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 19 Dec 2017 15:58:58 +0100 Subject: [PATCH 2/3] Workaround for GCC bug 51494 --- lib/icinga/comment.cpp | 2 +- lib/icinga/downtime.cpp | 2 +- lib/icinga/scheduleddowntime.cpp | 2 +- lib/icinga/timeperiod.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/icinga/comment.cpp b/lib/icinga/comment.cpp index 3bc736f15..9f354fc41 100644 --- a/lib/icinga/comment.cpp +++ b/lib/icinga/comment.cpp @@ -99,7 +99,7 @@ void Comment::Start(bool runtimeCreated) static boost::once_flag once = BOOST_ONCE_INIT; - boost::call_once(once, []() { + boost::call_once(once, [this]() { l_CommentsExpireTimer = new Timer(); l_CommentsExpireTimer->SetInterval(60); l_CommentsExpireTimer->OnTimerExpired.connect(std::bind(&Comment::CommentsExpireTimerHandler)); diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp index 2b5c325d7..df7dd99c4 100644 --- a/lib/icinga/downtime.cpp +++ b/lib/icinga/downtime.cpp @@ -103,7 +103,7 @@ void Downtime::Start(bool runtimeCreated) static boost::once_flag once = BOOST_ONCE_INIT; - boost::call_once(once, []() { + boost::call_once(once, [this]() { l_DowntimesStartTimer = new Timer(); l_DowntimesStartTimer->SetInterval(5); l_DowntimesStartTimer->OnTimerExpired.connect(std::bind(&Downtime::DowntimesStartTimerHandler)); diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index d3981fcb2..ac5c47c51 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -91,7 +91,7 @@ void ScheduledDowntime::Start(bool runtimeCreated) static boost::once_flag once = BOOST_ONCE_INIT; - boost::call_once(once, []() { + boost::call_once(once, [this]() { l_Timer = new Timer(); l_Timer->SetInterval(60); l_Timer->OnTimerExpired.connect(std::bind(&ScheduledDowntime::TimerProc)); diff --git a/lib/icinga/timeperiod.cpp b/lib/icinga/timeperiod.cpp index eed767c45..247b882e8 100644 --- a/lib/icinga/timeperiod.cpp +++ b/lib/icinga/timeperiod.cpp @@ -40,7 +40,7 @@ void TimePeriod::Start(bool runtimeCreated) static boost::once_flag once = BOOST_ONCE_INIT; - boost::call_once(once, []() { + boost::call_once(once, [this]() { l_UpdateTimer = new Timer(); l_UpdateTimer->SetInterval(300); l_UpdateTimer->OnTimerExpired.connect(std::bind(&TimePeriod::UpdateTimerHandler)); From 88af57e2ec047a62da5e729d8b4d0312df7673bb Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 19 Dec 2017 17:03:53 +0100 Subject: [PATCH 3/3] Fix for outdated libstdcxx --- test/remote-url.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/remote-url.cpp b/test/remote-url.cpp index 98ff16f47..b4b477e45 100644 --- a/test/remote-url.cpp +++ b/test/remote-url.cpp @@ -57,8 +57,8 @@ BOOST_AUTO_TEST_CASE(get_and_set) std::vector v1 { "hip", "hip", "hurra" }; std::vector v2 { "äü^ä+#ül-" }; std::vector v3 { "1", "2" }; - m.emplace("shout", v1); - m.emplace("sonderzeichen", v2); + m.insert(std::make_pair("shout", v1)); + m.insert(std::make_pair("sonderzeichen", v2)); url->SetQuery(m); url->SetQueryElements("count", v3); url->AddQueryElement("count", "3");