Properly handle libclang diagnostics

This commit is contained in:
Jonathan Müller 2017-03-16 12:15:46 +01:00
commit db0e649bf6
7 changed files with 79 additions and 13 deletions

View file

@ -93,7 +93,7 @@ struct libclang_parser::impl
{
detail::cxindex index;
impl() : index(clang_createIndex(1, 1))
impl() : index(clang_createIndex(0, 0)) // no diagnostic, other one is irrelevant
{
}
};
@ -117,7 +117,46 @@ namespace
return args;
}
detail::cxtranslation_unit get_cxunit(const detail::cxindex& idx,
type_safe::optional<severity> get_severity(const CXDiagnostic& diag)
{
switch (clang_getDiagnosticSeverity(diag))
{
case CXDiagnostic_Ignored:
case CXDiagnostic_Note:
case CXDiagnostic_Warning:
// ignore those diagnostics
return type_safe::nullopt;
case CXDiagnostic_Error:
return severity::error;
case CXDiagnostic_Fatal:
return severity::critical;
}
DEBUG_UNREACHABLE(detail::assert_handler{});
return type_safe::nullopt;
}
void print_diagnostics(const diagnostic_logger& logger, const char* path,
const CXTranslationUnit& tu)
{
auto no = clang_getNumDiagnostics(tu);
for (auto i = 0u; i != no; ++i)
{
auto diag = clang_getDiagnostic(tu, i);
auto sev = get_severity(diag);
if (sev)
{
auto loc = source_location::make_file(path); // line number won't help
auto text = detail::cxstring(clang_getDiagnosticSpelling(diag));
logger.log("libclang parser", diagnostic{text.c_str(), loc, sev.value()});
}
}
}
detail::cxtranslation_unit get_cxunit(const diagnostic_logger& logger,
const detail::cxindex& idx,
const libclang_compile_config& config, const char* path,
const std::string& source)
{
@ -155,6 +194,7 @@ namespace
throw libclang_error("clang_parseTranslationUnit: AST deserialization error");
}
}
print_diagnostics(logger, path, tu);
return detail::cxtranslation_unit(tu);
}
@ -178,8 +218,8 @@ std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx,
// preprocess + parse
auto preprocessed = detail::preprocess(config, path.c_str(), logger());
auto tu = get_cxunit(pimpl_->index, config, path.c_str(), preprocessed.source);
auto file = clang_getFile(tu.get(), path.c_str());
auto tu = get_cxunit(logger(), pimpl_->index, config, path.c_str(), preprocessed.source);
auto file = clang_getFile(tu.get(), path.c_str());
cpp_file::builder builder(path);
auto preprocessed_iter = preprocessed.entities.begin();

View file

@ -19,12 +19,12 @@ namespace cppast
{
inline source_location make_location(const CXCursor& cur)
{
return source_location::make(get_display_name(cur).c_str());
return source_location::make_entity(get_display_name(cur).c_str());
}
inline source_location make_location(const CXType& type)
{
return source_location::make(cxstring(clang_getTypeSpelling(type)).c_str());
return source_location::make_entity(cxstring(clang_getTypeSpelling(type)).c_str());
}
// thrown on a parsing error

View file

@ -330,7 +330,7 @@ namespace
{
auto msg = detail::format("unexpected type of kind '",
detail::get_type_kind_spelling(type).c_str(), "'");
auto location = source_location::make(get_type_spelling(type).c_str());
auto location = source_location::make_entity(get_type_spelling(type).c_str());
context.logger->log("libclang parser", diagnostic{msg, location, severity::warning});
}
// fallthrough

View file

@ -11,6 +11,13 @@
using namespace cppast;
bool diagnostic_logger::log(const char* source, const diagnostic& d) const
{
if (d.severity == severity::error)
error_ = true;
return do_log(source, d);
}
bool stderr_diagnostic_logger::do_log(const char* source, const diagnostic& d) const
{
std::fprintf(stderr, "[%s] [%s] %s %s\n", source, to_string(d.severity),