Skip to content

Commit

Permalink
Wired-up the new LLVM diagnostic system into clang diagnostic system.
Browse files Browse the repository at this point in the history
The approach is similar to the existing inline-asm reporting, just more
general.

<rdar://problem/15886278>

llvm-svn: 200931
  • Loading branch information
Quentin Colombet committed Feb 6, 2014
1 parent 9c0b64c commit 728c554
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 1 deletion.
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticCategories.td
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
//===----------------------------------------------------------------------===//

class CatInlineAsm : DiagCategory<"Inline Assembly Issue">;
class CatBackend : DiagCategory<"Backend Issue">;
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/DiagnosticFrontendKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,20 @@ def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;

// Error generated by the backend.
def err_fe_inline_asm : Error<"%0">, CatInlineAsm;
def warn_fe_inline_asm : Warning<"%0">, CatInlineAsm, InGroup<BackendInlineAsm>;
def note_fe_inline_asm : Note<"%0">, CatInlineAsm;
def note_fe_inline_asm_here : Note<"instantiated into assembly here">;
def err_fe_cannot_link_module : Error<"cannot link module '%0': %1">,
DefaultFatal;

def warn_fe_backend_frame_larger_than: Warning<"stack size exceeded (%0) in %1">,
CatBackend, InGroup<BackendFrameLargerThan>;
def err_fe_backend_frame_larger_than: Error<"%0">, CatBackend;
def note_fe_backend_frame_larger_than: Note<"%0">, CatBackend;

def warn_fe_backend_plugin: Warning<"%0">, CatBackend, InGroup<BackendPlugin>;
def err_fe_backend_plugin: Error<"%0">, CatBackend;
def note_fe_backend_plugin: Note<"%0">, CatBackend;

def err_fe_invalid_code_complete_file : Error<
"cannot locate code-completion file %0">, DefaultFatal;
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -625,3 +625,8 @@ def ASM : DiagGroup<"asm", [

// OpenMP warnings.
def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">;

// Backend warnings.
def BackendInlineAsm : DiagGroup<"inline-asm">;
def BackendFrameLargerThan : DiagGroup<"frame-larger-than">;
def BackendPlugin : DiagGroup<"backend-plugin">;
114 changes: 113 additions & 1 deletion clang/lib/CodeGen/CodeGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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() {}
Expand Down Expand Up @@ -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),
Expand Down
34 changes: 34 additions & 0 deletions clang/test/Frontend/backend-diagnostic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// REQUIRES: x86-registered-target
// Play around with backend reporting:
// _REGULAR_: Regular behavior, no warning switch enabled.
// _PROMOTE_: Promote warning to error.
// _IGNORE_: Drop backend warning.
//
// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -S -o - -triple=i386-apple-darwin 2> %t.err
// RUN: FileCheck < %t.err %s --check-prefix=REGULAR --check-prefix=ASM
// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -S -o - -triple=i386-apple-darwin -Werror=frame-larger-than 2> %t.err
// RUN: FileCheck < %t.err %s --check-prefix=PROMOTE --check-prefix=ASM
// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -S -o - -triple=i386-apple-darwin -Wno-frame-larger-than 2> %t.err
// RUN: FileCheck < %t.err %s --check-prefix=IGNORE --check-prefix=ASM
//
// Currently the stack size reporting cannot be checked with -verify because
// no source location is attached to the diagnostic. Therefore do not emit
// them for the -verify test for now.
// RUN: %clang_cc1 %s -S -o - -triple=i386-apple-darwin -verify

extern void doIt(char *);

// REGULAR: warning: stack size exceeded ({{[0-9]+}}) in stackSizeWarning
// PROMOTE: error: stack size exceeded ({{[0-9]+}}) in stackSizeWarning
// IGNORE-NOT: stack size exceeded ({{[0-9]+}}) in stackSizeWarning
void stackSizeWarning() {
char buffer[80];
doIt(buffer);
}

// ASM: inline assembly requires more registers than available
void inlineAsmError(int x0, int x1, int x2, int x3, int x4,
int x5, int x6, int x7, int x8, int x9) {
__asm__("hello world": : "r" (x0),"r" (x1),"r" (x2),"r" (x3), // expected-error + {{inline assembly requires more registers than available}}
"r" (x4),"r" (x5),"r" (x6),"r" (x7),"r" (x8),"r" (x9));
}

0 comments on commit 728c554

Please sign in to comment.