Skip to content

Commit 728c554

Browse files
author
Quentin Colombet
committed
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
1 parent 9c0b64c commit 728c554

File tree

5 files changed

+162
-1
lines changed

5 files changed

+162
-1
lines changed

clang/include/clang/Basic/DiagnosticCategories.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
//===----------------------------------------------------------------------===//
99

1010
class CatInlineAsm : DiagCategory<"Inline Assembly Issue">;
11+
class CatBackend : DiagCategory<"Backend Issue">;

clang/include/clang/Basic/DiagnosticFrontendKinds.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@ def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
1616

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

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

30+
def warn_fe_backend_plugin: Warning<"%0">, CatBackend, InGroup<BackendPlugin>;
31+
def err_fe_backend_plugin: Error<"%0">, CatBackend;
32+
def note_fe_backend_plugin: Note<"%0">, CatBackend;
2433

2534
def err_fe_invalid_code_complete_file : Error<
2635
"cannot locate code-completion file %0">, DefaultFatal;

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,3 +625,8 @@ def ASM : DiagGroup<"asm", [
625625

626626
// OpenMP warnings.
627627
def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">;
628+
629+
// Backend warnings.
630+
def BackendInlineAsm : DiagGroup<"inline-asm">;
631+
def BackendFrameLargerThan : DiagGroup<"frame-larger-than">;
632+
def BackendPlugin : DiagGroup<"backend-plugin">;

clang/lib/CodeGen/CodeGenAction.cpp

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "llvm/ADT/OwningPtr.h"
2222
#include "llvm/ADT/SmallString.h"
2323
#include "llvm/Bitcode/ReaderWriter.h"
24+
#include "llvm/IR/DiagnosticInfo.h"
25+
#include "llvm/IR/DiagnosticPrinter.h"
2426
#include "llvm/IR/LLVMContext.h"
2527
#include "llvm/IR/Module.h"
2628
#include "llvm/IRReader/IRReader.h"
@@ -149,11 +151,18 @@ namespace clang {
149151
void *OldContext = Ctx.getInlineAsmDiagnosticContext();
150152
Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this);
151153

154+
LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler =
155+
Ctx.getDiagnosticHandler();
156+
void *OldDiagnosticContext = Ctx.getDiagnosticContext();
157+
Ctx.setDiagnosticHandler(DiagnosticHandler, this);
158+
152159
EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
153160
C.getTargetInfo().getTargetDescription(),
154161
TheModule.get(), Action, AsmOutStream);
155162

156163
Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
164+
165+
Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext);
157166
}
158167

159168
virtual void HandleTagDeclDefinition(TagDecl *D) {
@@ -194,8 +203,23 @@ namespace clang {
194203
((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
195204
}
196205

206+
static void DiagnosticHandler(const llvm::DiagnosticInfo &DI,
207+
void *Context) {
208+
((BackendConsumer *)Context)->DiagnosticHandlerImpl(DI);
209+
}
210+
197211
void InlineAsmDiagHandler2(const llvm::SMDiagnostic &,
198212
SourceLocation LocCookie);
213+
214+
void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI);
215+
/// \brief Specialized handler for InlineAsm diagnostic.
216+
/// \return True if the diagnostic has been successfully reported, false
217+
/// otherwise.
218+
bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D);
219+
/// \brief Specialized handler for StackSize diagnostic.
220+
/// \return True if the diagnostic has been successfully reported, false
221+
/// otherwise.
222+
bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
199223
};
200224

201225
void BackendConsumer::anchor() {}
@@ -274,7 +298,95 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
274298
Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message);
275299
}
276300

277-
//
301+
#define ComputeDiagID(Severity, GroupName, DiagID) \
302+
do { \
303+
switch (Severity) { \
304+
case llvm::DS_Error: \
305+
DiagID = diag::err_fe_##GroupName; \
306+
break; \
307+
case llvm::DS_Warning: \
308+
DiagID = diag::warn_fe_##GroupName; \
309+
break; \
310+
case llvm::DS_Note: \
311+
DiagID = diag::note_fe_##GroupName; \
312+
break; \
313+
} \
314+
} while (false)
315+
316+
bool
317+
BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) {
318+
unsigned DiagID;
319+
ComputeDiagID(D.getSeverity(), inline_asm, DiagID);
320+
std::string Message = D.getMsgStr().str();
321+
322+
// If this problem has clang-level source location information, report the
323+
// issue as being a prbolem in the source with a note showing the instantiated
324+
// code.
325+
SourceLocation LocCookie =
326+
SourceLocation::getFromRawEncoding(D.getLocCookie());
327+
if (LocCookie.isValid())
328+
Diags.Report(LocCookie, DiagID).AddString(Message);
329+
else {
330+
// Otherwise, report the backend diagnostic as occurring in the generated
331+
// .s file.
332+
// If Loc is invalid, we still need to report the diagnostic, it just gets
333+
// no location info.
334+
FullSourceLoc Loc;
335+
Diags.Report(Loc, DiagID).AddString(Message);
336+
}
337+
// We handled all the possible severities.
338+
return true;
339+
}
340+
341+
bool
342+
BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) {
343+
if (D.getSeverity() != llvm::DS_Warning)
344+
// For now, the only support we have for StackSize diagnostic is warning.
345+
// We do not know how to format other severities.
346+
return false;
347+
348+
// FIXME: We should demangle the function name.
349+
// FIXME: Is there a way to get a location for that function?
350+
FullSourceLoc Loc;
351+
Diags.Report(Loc, diag::warn_fe_backend_frame_larger_than)
352+
<< D.getStackSize() << D.getFunction().getName();
353+
return true;
354+
}
355+
356+
/// \brief This function is invoked when the backend needs
357+
/// to report something to the user.
358+
void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
359+
unsigned DiagID = diag::err_fe_inline_asm;
360+
llvm::DiagnosticSeverity Severity = DI.getSeverity();
361+
// Get the diagnostic ID based.
362+
switch (DI.getKind()) {
363+
case llvm::DK_InlineAsm:
364+
if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI)))
365+
return;
366+
ComputeDiagID(Severity, inline_asm, DiagID);
367+
break;
368+
case llvm::DK_StackSize:
369+
if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI)))
370+
return;
371+
ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
372+
break;
373+
default:
374+
// Plugin IDs are not bound to any value as they are set dynamically.
375+
ComputeDiagID(Severity, backend_plugin, DiagID);
376+
break;
377+
}
378+
std::string MsgStorage;
379+
{
380+
raw_string_ostream Stream(MsgStorage);
381+
DiagnosticPrinterRawOStream DP(Stream);
382+
DI.print(DP);
383+
}
384+
385+
// Report the backend message using the usual diagnostic mechanism.
386+
FullSourceLoc Loc;
387+
Diags.Report(Loc, DiagID).AddString(MsgStorage);
388+
}
389+
#undef ComputeDiagID
278390

279391
CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
280392
: Act(_Act), LinkModule(0),
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// REQUIRES: x86-registered-target
2+
// Play around with backend reporting:
3+
// _REGULAR_: Regular behavior, no warning switch enabled.
4+
// _PROMOTE_: Promote warning to error.
5+
// _IGNORE_: Drop backend warning.
6+
//
7+
// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -S -o - -triple=i386-apple-darwin 2> %t.err
8+
// RUN: FileCheck < %t.err %s --check-prefix=REGULAR --check-prefix=ASM
9+
// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -S -o - -triple=i386-apple-darwin -Werror=frame-larger-than 2> %t.err
10+
// RUN: FileCheck < %t.err %s --check-prefix=PROMOTE --check-prefix=ASM
11+
// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -S -o - -triple=i386-apple-darwin -Wno-frame-larger-than 2> %t.err
12+
// RUN: FileCheck < %t.err %s --check-prefix=IGNORE --check-prefix=ASM
13+
//
14+
// Currently the stack size reporting cannot be checked with -verify because
15+
// no source location is attached to the diagnostic. Therefore do not emit
16+
// them for the -verify test for now.
17+
// RUN: %clang_cc1 %s -S -o - -triple=i386-apple-darwin -verify
18+
19+
extern void doIt(char *);
20+
21+
// REGULAR: warning: stack size exceeded ({{[0-9]+}}) in stackSizeWarning
22+
// PROMOTE: error: stack size exceeded ({{[0-9]+}}) in stackSizeWarning
23+
// IGNORE-NOT: stack size exceeded ({{[0-9]+}}) in stackSizeWarning
24+
void stackSizeWarning() {
25+
char buffer[80];
26+
doIt(buffer);
27+
}
28+
29+
// ASM: inline assembly requires more registers than available
30+
void inlineAsmError(int x0, int x1, int x2, int x3, int x4,
31+
int x5, int x6, int x7, int x8, int x9) {
32+
__asm__("hello world": : "r" (x0),"r" (x1),"r" (x2),"r" (x3), // expected-error + {{inline assembly requires more registers than available}}
33+
"r" (x4),"r" (x5),"r" (x6),"r" (x7),"r" (x8),"r" (x9));
34+
}

0 commit comments

Comments
 (0)