diff options
author | Joseph Reynolds <jrey@us.ibm.com> | 2018-05-04 10:11:00 -0500 |
---|---|---|
committer | Joseph Reynolds <jrey@us.ibm.com> | 2018-06-22 13:54:45 +0000 |
commit | 8f6f7fc3ccea4a1a32d17f4c335cbe7040fde068 (patch) | |
tree | 43cb86cca9362f47b7cdbaed7cae0b60d286d3eb | |
parent | 4a029f2f401a6738c6daa31ad3098eb7f0915c7c (diff) | |
download | phosphor-logging-8f6f7fc3ccea4a1a32d17f4c335cbe7040fde068.tar.gz phosphor-logging-8f6f7fc3ccea4a1a32d17f4c335cbe7040fde068.zip |
static_assert typeof log message entries
Please wait to commit this review until all of the code that
causes static_assert failures is committed.
Resolves openbmc/openbmc#2905
Tested: static_assert only
phosphor-logging now static_asserts that each item to be converted
by the printf-like function has integral, enum, floating_point, or
pointer type and each format argument has a type that decays to
a char * type.
Specifically, std::string fails the assertion because
its address would be logged and not the string buffer. You
probably want your strings to use s.c_str().
Note that we considered automatically applying c_str() to string
objects, but the underlying entry function is constexpr which
makes that impossible.
Change-Id: I88f6c626d58254eaad9b1a44e6a9c693d2fc6cd9
Signed-off-by: Joseph Reynolds <jrey@us.ibm.com>
-rw-r--r-- | phosphor-logging/log.hpp | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/phosphor-logging/log.hpp b/phosphor-logging/log.hpp index a5ba738..a933591 100644 --- a/phosphor-logging/log.hpp +++ b/phosphor-logging/log.hpp @@ -17,6 +17,7 @@ #pragma once #include <tuple> +#include <type_traits> #include <systemd/sd-journal.h> #include <sdbusplus/server/transaction.hpp> @@ -135,11 +136,43 @@ void log(Msg msg, Entry... e) details::log(log_tuple); } +template<class T> +struct is_printf_argtype + : std::integral_constant< + bool, + (std::is_integral<typename std::remove_reference<T>::type>::value || + std::is_enum<typename std::remove_reference<T>::type>::value || + std::is_floating_point<typename + std::remove_reference<T>::type>::value || + std::is_pointer<typename std::decay<T>::type>::value)> +{}; + +template<class T> +struct is_char_ptr_argtype + : std::integral_constant< + bool, + (std::is_pointer<typename std::decay<T>::type>::value && + std::is_same<typename std::remove_cv<typename + std::remove_pointer<typename + std::decay<T>::type>::type>::type, + char>::value)> +{}; + +template<bool...> +struct bool_pack; + +template<bool... bs> +using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>; + template <typename Arg, typename ...Args> constexpr auto entry(Arg&& arg, Args&&... args) { + static_assert(is_char_ptr_argtype<Arg>::value, + "bad argument type: use char*"); + static_assert(all_true<is_printf_argtype<Args>::value...>::value, + "bad argument type: use string.c_str() if needed"); const auto entry_tuple = std::make_tuple(std::forward<Arg>(arg), - std::forward<Args>(args)...); + std::forward<Args>(args)...); return entry_tuple; } |