|
21 | 21 | #include "llvm/ADT/OwningPtr.h"
|
22 | 22 | #include "llvm/ADT/SmallString.h"
|
23 | 23 | #include "llvm/Bitcode/ReaderWriter.h"
|
| 24 | +#include "llvm/IR/DiagnosticInfo.h" |
| 25 | +#include "llvm/IR/DiagnosticPrinter.h" |
24 | 26 | #include "llvm/IR/LLVMContext.h"
|
25 | 27 | #include "llvm/IR/Module.h"
|
26 | 28 | #include "llvm/IRReader/IRReader.h"
|
@@ -149,11 +151,18 @@ namespace clang {
|
149 | 151 | void *OldContext = Ctx.getInlineAsmDiagnosticContext();
|
150 | 152 | Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this);
|
151 | 153 |
|
| 154 | + LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler = |
| 155 | + Ctx.getDiagnosticHandler(); |
| 156 | + void *OldDiagnosticContext = Ctx.getDiagnosticContext(); |
| 157 | + Ctx.setDiagnosticHandler(DiagnosticHandler, this); |
| 158 | + |
152 | 159 | EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
|
153 | 160 | C.getTargetInfo().getTargetDescription(),
|
154 | 161 | TheModule.get(), Action, AsmOutStream);
|
155 | 162 |
|
156 | 163 | Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
|
| 164 | + |
| 165 | + Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext); |
157 | 166 | }
|
158 | 167 |
|
159 | 168 | virtual void HandleTagDeclDefinition(TagDecl *D) {
|
@@ -194,8 +203,23 @@ namespace clang {
|
194 | 203 | ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
|
195 | 204 | }
|
196 | 205 |
|
| 206 | + static void DiagnosticHandler(const llvm::DiagnosticInfo &DI, |
| 207 | + void *Context) { |
| 208 | + ((BackendConsumer *)Context)->DiagnosticHandlerImpl(DI); |
| 209 | + } |
| 210 | + |
197 | 211 | void InlineAsmDiagHandler2(const llvm::SMDiagnostic &,
|
198 | 212 | 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); |
199 | 223 | };
|
200 | 224 |
|
201 | 225 | void BackendConsumer::anchor() {}
|
@@ -274,7 +298,95 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
|
274 | 298 | Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message);
|
275 | 299 | }
|
276 | 300 |
|
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 |
278 | 390 |
|
279 | 391 | CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
|
280 | 392 | : Act(_Act), LinkModule(0),
|
|
0 commit comments