diff --git a/include/cppast/diagnostic.hpp b/include/cppast/diagnostic.hpp index ba7d547..e73a994 100644 --- a/include/cppast/diagnostic.hpp +++ b/include/cppast/diagnostic.hpp @@ -5,6 +5,7 @@ #ifndef CPPAST_DIAGNOSTIC_HPP_INCLUDED #define CPPAST_DIAGNOSTIC_HPP_INCLUDED +#include #include #include @@ -112,6 +113,27 @@ namespace cppast source_location location; cppast::severity severity; }; + + namespace detail + { + template + std::string format(Args&&... args) + { + std::ostringstream stream; + int dummy[] = {(stream << std::forward(args), 0)...}; + (void)dummy; + return stream.str(); + } + } // namespace detail + + /// Creates a diagnostic. + /// \returns A diagnostic with the specified severity and location. + /// The message is created by streaming each argument in order to a [std::ostringstream](). + template + diagnostic format_diagnostic(severity sev, source_location loc, Args&&... args) + { + return {detail::format(std::forward(args)...), std::move(loc), sev}; + } } // namespace cppast #endif // CPPAST_DIAGNOSTIC_HPP_INCLUDED diff --git a/src/libclang/parse_error.hpp b/src/libclang/parse_error.hpp index bb40f2d..ba7606b 100644 --- a/src/libclang/parse_error.hpp +++ b/src/libclang/parse_error.hpp @@ -6,7 +6,6 @@ #define CPPAST_PARSE_ERROR_HPP_INCLUDED #include -#include #include #include @@ -78,15 +77,6 @@ namespace cppast throw parse_error(type, std::move(message)); } }; - - template - std::string format(Args&&... args) - { - std::ostringstream stream; - int dummy[] = {(stream << std::forward(args), 0)...}; - (void)dummy; - return stream.str(); - } } } // namespace cppast::detail diff --git a/src/libclang/parse_functions.cpp b/src/libclang/parse_functions.cpp index 06631eb..6b4b471 100644 --- a/src/libclang/parse_functions.cpp +++ b/src/libclang/parse_functions.cpp @@ -113,11 +113,10 @@ std::unique_ptr detail::parse_entity(const detail::parse_context& co { if (context.logger->is_verbose()) { - auto message = detail::format("parsing cursor of type '", - detail::get_cursor_kind_spelling(cur).c_str(), "'"); context.logger->log("libclang parser", - diagnostic{std::move(message), detail::make_location(cur), - severity::debug}); + format_diagnostic(severity::debug, detail::make_location(cur), + "parsing cursor of type '", + detail::get_cursor_kind_spelling(cur).c_str(), "'")); } auto kind = clang_getCursorKind(cur); @@ -211,8 +210,9 @@ std::unique_ptr detail::parse_entity(const detail::parse_context& co auto msg = detail::format("unhandled cursor of kind '", detail::get_cursor_kind_spelling(cur).c_str(), "'"); context.logger->log("libclang parser", - diagnostic{std::move(msg), detail::make_location(cur), - severity::warning}); + format_diagnostic(severity::warning, detail::make_location(cur), + "unhandled cursor of kind '", + detail::get_cursor_kind_spelling(cur).c_str(), "'")); // build unexposed entity auto name = detail::get_cursor_name(cur); diff --git a/src/libclang/preprocessor.cpp b/src/libclang/preprocessor.cpp index ae75e7b..11efc1a 100644 --- a/src/libclang/preprocessor.cpp +++ b/src/libclang/preprocessor.cpp @@ -708,13 +708,10 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co else if (auto macro = parse_macro(p, result, file_depth == 0u)) { if (logger.is_verbose()) - { - auto message = detail::format("parsing macro '", macro->name(), "'"); logger.log("preprocessor", - diagnostic{std::move(message), - source_location::make_file(path, p.cur_line()), - severity::debug}); - } + format_diagnostic(severity::debug, + source_location::make_file(path, p.cur_line()), + "parsing macro '", macro->name(), "'")); result.macros.push_back({std::move(macro), p.cur_line()}); } @@ -723,13 +720,11 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co if (file_depth == 0u) { if (logger.is_verbose()) - { - auto message = detail::format("undefining macro '", undef.value(), "'"); logger.log("preprocessor", - diagnostic{std::move(message), - source_location::make_file(path, p.cur_line()), - severity::debug}); - } + format_diagnostic(severity::debug, + source_location::make_file(path, p.cur_line()), + "undefining macro '", undef.value(), "'")); + result.macros.erase(std::remove_if(result.macros.begin(), result.macros.end(), [&](const pp_macro& e) { return e.macro->name() == undef.value(); @@ -740,14 +735,12 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co else if (auto include = parse_include(p, file_depth == 0u)) { if (logger.is_verbose()) - { - auto message = - detail::format("parsing include '", include.value().file.name(), "'"); logger.log("preprocessor", - diagnostic{std::move(message), - source_location::make_file(path, p.cur_line()), - severity::debug}); - } + format_diagnostic(severity::debug, + source_location::make_file(path, p.cur_line()), + "parsing include '", include.value().file.name(), + "'")); + result.includes.push_back(std::move(include.value())); } else if (bump_pragma(p)) diff --git a/src/libclang/type_parser.cpp b/src/libclang/type_parser.cpp index 9603992..cdd841a 100644 --- a/src/libclang/type_parser.cpp +++ b/src/libclang/type_parser.cpp @@ -552,12 +552,11 @@ namespace case CXType_OCLQueue: case CXType_OCLReserveID: #endif - { - auto msg = detail::format("unexpected type of kind '", - detail::get_type_kind_spelling(type).c_str(), "'"); - auto location = detail::make_location(type); - context.logger->log("libclang parser", diagnostic{msg, location, severity::warning}); - } + context.logger->log("libclang parser", + format_diagnostic(severity::warning, detail::make_location(type), + "unexpected type of kind '", + detail::get_type_kind_spelling(type).c_str(), + "'")); // fallthrough case CXType_Dependent: // seems to have something to do with expressions, just ignore that (for now?) case CXType_Unexposed: