diff options
Diffstat (limited to 'tools/diagtool/ShowEnabledWarnings.cpp')
-rw-r--r-- | tools/diagtool/ShowEnabledWarnings.cpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/tools/diagtool/ShowEnabledWarnings.cpp b/tools/diagtool/ShowEnabledWarnings.cpp new file mode 100644 index 0000000..7162451 --- /dev/null +++ b/tools/diagtool/ShowEnabledWarnings.cpp @@ -0,0 +1,148 @@ +//===- ShowEnabledWarnings - diagtool tool for printing enabled flags -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DiagTool.h" +#include "DiagnosticNames.h" +#include "clang/Basic/LLVM.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Frontend/Utils.h" +#include "llvm/Support/TargetSelect.h" + +DEF_DIAGTOOL("show-enabled", + "Show which warnings are enabled for a given command line", + ShowEnabledWarnings) + +using namespace clang; +using namespace diagtool; + +namespace { + struct PrettyDiag { + StringRef Name; + StringRef Flag; + DiagnosticsEngine::Level Level; + + PrettyDiag(StringRef name, StringRef flag, DiagnosticsEngine::Level level) + : Name(name), Flag(flag), Level(level) {} + + bool operator<(const PrettyDiag &x) const { return Name < x.Name; } + }; +} + +static void printUsage() { + llvm::errs() << "Usage: diagtool show-enabled [<flags>] <single-input.c>\n"; +} + +static char getCharForLevel(DiagnosticsEngine::Level Level) { + switch (Level) { + case DiagnosticsEngine::Ignored: return ' '; + case DiagnosticsEngine::Note: return '-'; + case DiagnosticsEngine::Warning: return 'W'; + case DiagnosticsEngine::Error: return 'E'; + case DiagnosticsEngine::Fatal: return 'F'; + } + + llvm_unreachable("Unknown diagnostic level"); +} + +static IntrusiveRefCntPtr<DiagnosticsEngine> +createDiagnostics(unsigned int argc, char **argv) { + IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs()); + + // Buffer diagnostics from argument parsing so that we can output them using a + // well formed diagnostic object. + TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; + IntrusiveRefCntPtr<DiagnosticsEngine> InterimDiags( + new DiagnosticsEngine(DiagIDs, DiagsBuffer)); + + // Try to build a CompilerInvocation. + OwningPtr<CompilerInvocation> Invocation( + createInvocationFromCommandLine(ArrayRef<const char *>(argv, argc), + InterimDiags)); + if (!Invocation) + return NULL; + + // Build the diagnostics parser + IntrusiveRefCntPtr<DiagnosticsEngine> FinalDiags = + CompilerInstance::createDiagnostics(Invocation->getDiagnosticOpts(), + argc, argv); + if (!FinalDiags) + return NULL; + + // Flush any errors created when initializing everything. This could happen + // for invalid command lines, which will probably give non-sensical results. + DiagsBuffer->FlushDiagnostics(*FinalDiags); + + return FinalDiags; +} + +int ShowEnabledWarnings::run(unsigned int argc, char **argv, raw_ostream &Out) { + // First check our one flag (--levels). + bool ShouldShowLevels = true; + if (argc > 0) { + StringRef FirstArg(*argv); + if (FirstArg.equals("--no-levels")) { + ShouldShowLevels = false; + --argc; + ++argv; + } else if (FirstArg.equals("--levels")) { + ShouldShowLevels = true; + --argc; + ++argv; + } + } + + // Create the diagnostic engine. + IntrusiveRefCntPtr<DiagnosticsEngine> Diags = createDiagnostics(argc, argv); + if (!Diags) { + printUsage(); + return EXIT_FAILURE; + } + + // Now we have our diagnostics. Iterate through EVERY diagnostic and see + // which ones are turned on. + // FIXME: It would be very nice to print which flags are turning on which + // diagnostics, but this can be done with a diff. + ArrayRef<DiagnosticRecord> AllDiagnostics = getBuiltinDiagnosticsByName(); + std::vector<PrettyDiag> Active; + + for (ArrayRef<DiagnosticRecord>::iterator I = AllDiagnostics.begin(), + E = AllDiagnostics.end(); + I != E; ++I) { + unsigned DiagID = I->DiagID; + + if (DiagnosticIDs::isBuiltinNote(DiagID)) + continue; + + if (!DiagnosticIDs::isBuiltinWarningOrExtension(DiagID)) + continue; + + DiagnosticsEngine::Level DiagLevel = + Diags->getDiagnosticLevel(DiagID, SourceLocation()); + if (DiagLevel == DiagnosticsEngine::Ignored) + continue; + + StringRef WarningOpt = DiagnosticIDs::getWarningOptionForDiag(DiagID); + Active.push_back(PrettyDiag(I->getName(), WarningOpt, DiagLevel)); + } + + // Print them all out. + for (std::vector<PrettyDiag>::const_iterator I = Active.begin(), + E = Active.end(); I != E; ++I) { + if (ShouldShowLevels) + Out << getCharForLevel(I->Level) << " "; + Out << I->Name; + if (!I->Flag.empty()) + Out << " [-W" << I->Flag << "]"; + Out << '\n'; + } + + return EXIT_SUCCESS; +} |