]> granicus.if.org Git - clang/commitdiff
Wired-up the new LLVM diagnostic system into clang diagnostic system.
authorQuentin Colombet <qcolombet@apple.com>
Thu, 6 Feb 2014 18:30:43 +0000 (18:30 +0000)
committerQuentin Colombet <qcolombet@apple.com>
Thu, 6 Feb 2014 18:30:43 +0000 (18:30 +0000)
The approach is similar to the existing inline-asm reporting, just more
general.

<rdar://problem/15886278>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200931 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticCategories.td
include/clang/Basic/DiagnosticFrontendKinds.td
include/clang/Basic/DiagnosticGroups.td
lib/CodeGen/CodeGenAction.cpp
test/Frontend/backend-diagnostic.c [new file with mode: 0644]

index a02fbdf93fc3d845ef173de9a6ee635159079581..37b856976d52785808ea817fd74ed152903fe7f7 100644 (file)
@@ -8,3 +8,4 @@
 //===----------------------------------------------------------------------===//
 
 class CatInlineAsm : DiagCategory<"Inline Assembly Issue">;
+class CatBackend : DiagCategory<"Backend Issue">;
index b0b140d61924f634bdceed03e14738acb7a570b0..21809ad63ff1f09b9f7165e2ab03678e0e46774f 100644 (file)
@@ -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;
index 8e9ef688c6f901d0687d88a23d975f61f162be09..441b5af4cda97977c661a284938677cbbfc03e62 100644 (file)
@@ -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">;
index ef44c96bb6bccb99c4fa5fbca4804c21c2f9d79c..5f66ba1735e9e9dfb51ccca19747fe8f46f6bcdd 100644 (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),
diff --git a/test/Frontend/backend-diagnostic.c b/test/Frontend/backend-diagnostic.c
new file mode 100644 (file)
index 0000000..acb15f2
--- /dev/null
@@ -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));
+}