Wired-up the new LLVM diagnostic system into clang diagnostic system.

The approach is similar to the existing inline-asm reporting, just more
general.

<rdar://problem/15886278>

llvm-svn: 200931
This commit is contained in:
Quentin Colombet
2014-02-06 18:30:43 +00:00
parent 9c0b64c92d
commit 728c5540ee
5 changed files with 162 additions and 1 deletions

View File

@@ -21,6 +21,8 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
@@ -149,11 +151,18 @@ namespace clang {
void *OldContext = Ctx.getInlineAsmDiagnosticContext();
Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this);
LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler =
Ctx.getDiagnosticHandler();
void *OldDiagnosticContext = Ctx.getDiagnosticContext();
Ctx.setDiagnosticHandler(DiagnosticHandler, this);
EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
C.getTargetInfo().getTargetDescription(),
TheModule.get(), Action, AsmOutStream);
Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext);
}
virtual void HandleTagDeclDefinition(TagDecl *D) {
@@ -194,8 +203,23 @@ namespace clang {
((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
}
static void DiagnosticHandler(const llvm::DiagnosticInfo &DI,
void *Context) {
((BackendConsumer *)Context)->DiagnosticHandlerImpl(DI);
}
void InlineAsmDiagHandler2(const llvm::SMDiagnostic &,
SourceLocation LocCookie);
void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI);
/// \brief Specialized handler for InlineAsm diagnostic.
/// \return True if the diagnostic has been successfully reported, false
/// otherwise.
bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D);
/// \brief Specialized handler for StackSize diagnostic.
/// \return True if the diagnostic has been successfully reported, false
/// otherwise.
bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
};
void BackendConsumer::anchor() {}
@@ -274,7 +298,95 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message);
}
//
#define ComputeDiagID(Severity, GroupName, DiagID) \
do { \
switch (Severity) { \
case llvm::DS_Error: \
DiagID = diag::err_fe_##GroupName; \
break; \
case llvm::DS_Warning: \
DiagID = diag::warn_fe_##GroupName; \
break; \
case llvm::DS_Note: \
DiagID = diag::note_fe_##GroupName; \
break; \
} \
} while (false)
bool
BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) {
unsigned DiagID;
ComputeDiagID(D.getSeverity(), inline_asm, DiagID);
std::string Message = D.getMsgStr().str();
// If this problem has clang-level source location information, report the
// issue as being a prbolem in the source with a note showing the instantiated
// code.
SourceLocation LocCookie =
SourceLocation::getFromRawEncoding(D.getLocCookie());
if (LocCookie.isValid())
Diags.Report(LocCookie, DiagID).AddString(Message);
else {
// Otherwise, report the backend diagnostic as occurring in the generated
// .s file.
// If Loc is invalid, we still need to report the diagnostic, it just gets
// no location info.
FullSourceLoc Loc;
Diags.Report(Loc, DiagID).AddString(Message);
}
// We handled all the possible severities.
return true;
}
bool
BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) {
if (D.getSeverity() != llvm::DS_Warning)
// For now, the only support we have for StackSize diagnostic is warning.
// We do not know how to format other severities.
return false;
// FIXME: We should demangle the function name.
// FIXME: Is there a way to get a location for that function?
FullSourceLoc Loc;
Diags.Report(Loc, diag::warn_fe_backend_frame_larger_than)
<< D.getStackSize() << D.getFunction().getName();
return true;
}
/// \brief This function is invoked when the backend needs
/// to report something to the user.
void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
unsigned DiagID = diag::err_fe_inline_asm;
llvm::DiagnosticSeverity Severity = DI.getSeverity();
// Get the diagnostic ID based.
switch (DI.getKind()) {
case llvm::DK_InlineAsm:
if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI)))
return;
ComputeDiagID(Severity, inline_asm, DiagID);
break;
case llvm::DK_StackSize:
if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI)))
return;
ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
break;
default:
// Plugin IDs are not bound to any value as they are set dynamically.
ComputeDiagID(Severity, backend_plugin, DiagID);
break;
}
std::string MsgStorage;
{
raw_string_ostream Stream(MsgStorage);
DiagnosticPrinterRawOStream DP(Stream);
DI.print(DP);
}
// Report the backend message using the usual diagnostic mechanism.
FullSourceLoc Loc;
Diags.Report(Loc, DiagID).AddString(MsgStorage);
}
#undef ComputeDiagID
CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
: Act(_Act), LinkModule(0),