ShowEnabledWarnings.cpp revision 651f13cea278ec967336033dd032faef0e9fc2ec
1//===- ShowEnabledWarnings - diagtool tool for printing enabled flags -----===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "DiagTool.h" 11#include "DiagnosticNames.h" 12#include "clang/Basic/LLVM.h" 13#include "clang/Frontend/CompilerInstance.h" 14#include "clang/Frontend/TextDiagnosticBuffer.h" 15#include "clang/Frontend/TextDiagnosticPrinter.h" 16#include "clang/Frontend/Utils.h" 17#include "llvm/Support/TargetSelect.h" 18 19DEF_DIAGTOOL("show-enabled", 20 "Show which warnings are enabled for a given command line", 21 ShowEnabledWarnings) 22 23using namespace clang; 24using namespace diagtool; 25 26namespace { 27 struct PrettyDiag { 28 StringRef Name; 29 StringRef Flag; 30 DiagnosticsEngine::Level Level; 31 32 PrettyDiag(StringRef name, StringRef flag, DiagnosticsEngine::Level level) 33 : Name(name), Flag(flag), Level(level) {} 34 35 bool operator<(const PrettyDiag &x) const { return Name < x.Name; } 36 }; 37} 38 39static void printUsage() { 40 llvm::errs() << "Usage: diagtool show-enabled [<flags>] <single-input.c>\n"; 41} 42 43static char getCharForLevel(DiagnosticsEngine::Level Level) { 44 switch (Level) { 45 case DiagnosticsEngine::Ignored: return ' '; 46 case DiagnosticsEngine::Note: return '-'; 47 case DiagnosticsEngine::Remark: return 'R'; 48 case DiagnosticsEngine::Warning: return 'W'; 49 case DiagnosticsEngine::Error: return 'E'; 50 case DiagnosticsEngine::Fatal: return 'F'; 51 } 52 53 llvm_unreachable("Unknown diagnostic level"); 54} 55 56static IntrusiveRefCntPtr<DiagnosticsEngine> 57createDiagnostics(unsigned int argc, char **argv) { 58 IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs()); 59 60 // Buffer diagnostics from argument parsing so that we can output them using a 61 // well formed diagnostic object. 62 TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 63 IntrusiveRefCntPtr<DiagnosticsEngine> InterimDiags( 64 new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer)); 65 66 // Try to build a CompilerInvocation. 67 std::unique_ptr<CompilerInvocation> Invocation( 68 createInvocationFromCommandLine(ArrayRef<const char *>(argv, argc), 69 InterimDiags)); 70 if (!Invocation) 71 return NULL; 72 73 // Build the diagnostics parser 74 IntrusiveRefCntPtr<DiagnosticsEngine> FinalDiags = 75 CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts()); 76 if (!FinalDiags) 77 return NULL; 78 79 // Flush any errors created when initializing everything. This could happen 80 // for invalid command lines, which will probably give non-sensical results. 81 DiagsBuffer->FlushDiagnostics(*FinalDiags); 82 83 return FinalDiags; 84} 85 86int ShowEnabledWarnings::run(unsigned int argc, char **argv, raw_ostream &Out) { 87 // First check our one flag (--levels). 88 bool ShouldShowLevels = true; 89 if (argc > 0) { 90 StringRef FirstArg(*argv); 91 if (FirstArg.equals("--no-levels")) { 92 ShouldShowLevels = false; 93 --argc; 94 ++argv; 95 } else if (FirstArg.equals("--levels")) { 96 ShouldShowLevels = true; 97 --argc; 98 ++argv; 99 } 100 } 101 102 // Create the diagnostic engine. 103 IntrusiveRefCntPtr<DiagnosticsEngine> Diags = createDiagnostics(argc, argv); 104 if (!Diags) { 105 printUsage(); 106 return EXIT_FAILURE; 107 } 108 109 // Now we have our diagnostics. Iterate through EVERY diagnostic and see 110 // which ones are turned on. 111 // FIXME: It would be very nice to print which flags are turning on which 112 // diagnostics, but this can be done with a diff. 113 ArrayRef<DiagnosticRecord> AllDiagnostics = getBuiltinDiagnosticsByName(); 114 std::vector<PrettyDiag> Active; 115 116 for (ArrayRef<DiagnosticRecord>::iterator I = AllDiagnostics.begin(), 117 E = AllDiagnostics.end(); 118 I != E; ++I) { 119 unsigned DiagID = I->DiagID; 120 121 if (DiagnosticIDs::isBuiltinNote(DiagID)) 122 continue; 123 124 if (!DiagnosticIDs::isBuiltinWarningOrExtension(DiagID)) 125 continue; 126 127 DiagnosticsEngine::Level DiagLevel = 128 Diags->getDiagnosticLevel(DiagID, SourceLocation()); 129 if (DiagLevel == DiagnosticsEngine::Ignored) 130 continue; 131 132 StringRef WarningOpt = DiagnosticIDs::getWarningOptionForDiag(DiagID); 133 Active.push_back(PrettyDiag(I->getName(), WarningOpt, DiagLevel)); 134 } 135 136 // Print them all out. 137 for (std::vector<PrettyDiag>::const_iterator I = Active.begin(), 138 E = Active.end(); I != E; ++I) { 139 if (ShouldShowLevels) 140 Out << getCharForLevel(I->Level) << " "; 141 Out << I->Name; 142 if (!I->Flag.empty()) 143 Out << " [-W" << I->Flag << "]"; 144 Out << '\n'; 145 } 146 147 return EXIT_SUCCESS; 148} 149