Skip to content

Commit

Permalink
Adding C++ compiler diagnostic messages to the database (Ericsson#403)
Browse files Browse the repository at this point in the history
Adding diagnostic messages to the database.
clang::DiagnosticConsumer is handling the diagnostic messages (compilation
errors, warnings, notes, etc.) during C/C++ compilation. These diagnostic
messages are collected and stored in the database.
  • Loading branch information
bruntib authored Jul 31, 2020
1 parent 0f3ab69 commit de4ce6f
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 6 deletions.
4 changes: 0 additions & 4 deletions model/include/model/buildlog.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@ struct BuildLog
#pragma db not_null
BuildLogMessage log;

#pragma db not_null
#pragma db on_delete(cascade)
std::shared_ptr<BuildAction> action;

#pragma db null
FileLoc location;
};
Expand Down
3 changes: 2 additions & 1 deletion plugins/cpp/parser/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ add_library(cppparser SHARED
src/ppincludecallback.cpp
src/ppmacrocallback.cpp
src/relationcollector.cpp
src/doccommentformatter.cpp)
src/doccommentformatter.cpp
src/diagnosticmessagehandler.cpp)

target_link_libraries(cppparser
cppmodel
Expand Down
2 changes: 1 addition & 1 deletion plugins/cpp/parser/include/cppparser/filelocutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class FileLocUtil
*/
std::string getFilePath(const clang::SourceLocation& loc_)
{
clang::SourceLocation expLoc =_clangSrcMan.getExpansionLoc(loc_);
clang::SourceLocation expLoc = _clangSrcMan.getExpansionLoc(loc_);
clang::FileID fid = _clangSrcMan.getFileID(expLoc);

if (fid.isInvalid())
Expand Down
4 changes: 4 additions & 0 deletions plugins/cpp/parser/src/cppparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "ppincludecallback.h"
#include "ppmacrocallback.h"
#include "doccommentcollector.h"
#include "diagnosticmessagehandler.h"

namespace cc
{
Expand Down Expand Up @@ -325,6 +326,9 @@ int CppParser::parseWorker(const clang::tooling::CompileCommand& command_)
VisitorActionFactory factory(_ctx);
clang::tooling::ClangTool tool(*compilationDb, command_.Filename);

DiagnosticMessageHandler diagMsgHandler(_ctx.srcMgr, _ctx.db);
tool.setDiagnosticConsumer(&diagMsgHandler);

int error = tool.run(&factory);

//--- Save build command ---//
Expand Down
75 changes: 75 additions & 0 deletions plugins/cpp/parser/src/diagnosticmessagehandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <llvm/ADT/SmallString.h>
#include <cppparser/filelocutil.h>
#include "diagnosticmessagehandler.h"

namespace cc
{
namespace parser
{

DiagnosticMessageHandler::DiagnosticMessageHandler(
SourceManager& srcMgr_,
std::shared_ptr<odb::database> db_)
: _srcMgr(srcMgr_), _db(db_)
{
}

void DiagnosticMessageHandler::HandleDiagnostic(
clang::DiagnosticsEngine::Level diagLevel_,
const clang::Diagnostic& info_)
{
clang::DiagnosticConsumer::HandleDiagnostic(diagLevel_, info_);

model::BuildLog buildLog;

//--- Message type ---//

switch (diagLevel_)
{
case clang::DiagnosticsEngine::Note:
buildLog.log.type = model::BuildLogMessage::Note;
break;
case clang::DiagnosticsEngine::Warning:
buildLog.log.type = model::BuildLogMessage::Warning;
break;
case clang::DiagnosticsEngine::Error:
buildLog.log.type = model::BuildLogMessage::Error;
break;
case clang::DiagnosticsEngine::Fatal:
buildLog.log.type = model::BuildLogMessage::FatalError;
break;
}

//--- Message content ---//

llvm::SmallString<512> content;
info_.FormatDiagnostic(content);
buildLog.log.message = content.c_str();

//--- Message location ---//

if (info_.getLocation().isValid() && info_.hasSourceManager())
{
FileLocUtil fileLocUtil(info_.getSourceManager());
const clang::SourceLocation& loc = info_.getLocation();

model::Range fileLoc;
fileLocUtil.setRange(loc, loc, fileLoc);

buildLog.location.range = fileLoc;
buildLog.location.file = _srcMgr.getFile(fileLocUtil.getFilePath(loc));
}

_messages.push_back(buildLog);
}

DiagnosticMessageHandler::~DiagnosticMessageHandler()
{
util::OdbTransaction{_db}([this](){
for (model::BuildLog& message : _messages)
_db->persist(message);
});
}

}
}
35 changes: 35 additions & 0 deletions plugins/cpp/parser/src/diagnosticmessagehandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef CC_PARSER_DIAGNOSTICMESSAGEHANDLER_H
#define CC_PARSER_DIAGNOSTICMESSAGEHANDLER_H

#include <vector>
#include <clang/Basic/Diagnostic.h>
#include <model/buildlog-odb.hxx>
#include <parser/sourcemanager.h>

namespace cc
{
namespace parser
{

class DiagnosticMessageHandler : public clang::DiagnosticConsumer
{
public:
DiagnosticMessageHandler(
SourceManager& srcMgr_,
std::shared_ptr<odb::database> db_);
~DiagnosticMessageHandler();

void HandleDiagnostic(
clang::DiagnosticsEngine::Level diagLevel_,
const clang::Diagnostic& info_) override;

private:
SourceManager& _srcMgr;
std::vector<model::BuildLog> _messages;
std::shared_ptr<odb::database> _db;
};

}
}

#endif

0 comments on commit de4ce6f

Please sign in to comment.