10832f82f763185767d63ae4bf05021c5630c155fJordan Rose//===- ShowEnabledWarnings - diagtool tool for printing enabled flags -----===//
20832f82f763185767d63ae4bf05021c5630c155fJordan Rose//
30832f82f763185767d63ae4bf05021c5630c155fJordan Rose//                     The LLVM Compiler Infrastructure
40832f82f763185767d63ae4bf05021c5630c155fJordan Rose//
50832f82f763185767d63ae4bf05021c5630c155fJordan Rose// This file is distributed under the University of Illinois Open Source
60832f82f763185767d63ae4bf05021c5630c155fJordan Rose// License. See LICENSE.TXT for details.
70832f82f763185767d63ae4bf05021c5630c155fJordan Rose//
80832f82f763185767d63ae4bf05021c5630c155fJordan Rose//===----------------------------------------------------------------------===//
90832f82f763185767d63ae4bf05021c5630c155fJordan Rose
100832f82f763185767d63ae4bf05021c5630c155fJordan Rose#include "DiagTool.h"
110832f82f763185767d63ae4bf05021c5630c155fJordan Rose#include "DiagnosticNames.h"
120832f82f763185767d63ae4bf05021c5630c155fJordan Rose#include "clang/Basic/LLVM.h"
130832f82f763185767d63ae4bf05021c5630c155fJordan Rose#include "clang/Frontend/CompilerInstance.h"
140832f82f763185767d63ae4bf05021c5630c155fJordan Rose#include "clang/Frontend/TextDiagnosticBuffer.h"
150832f82f763185767d63ae4bf05021c5630c155fJordan Rose#include "clang/Frontend/TextDiagnosticPrinter.h"
160832f82f763185767d63ae4bf05021c5630c155fJordan Rose#include "clang/Frontend/Utils.h"
170832f82f763185767d63ae4bf05021c5630c155fJordan Rose#include "llvm/Support/TargetSelect.h"
180832f82f763185767d63ae4bf05021c5630c155fJordan Rose
190832f82f763185767d63ae4bf05021c5630c155fJordan RoseDEF_DIAGTOOL("show-enabled",
200832f82f763185767d63ae4bf05021c5630c155fJordan Rose             "Show which warnings are enabled for a given command line",
210832f82f763185767d63ae4bf05021c5630c155fJordan Rose             ShowEnabledWarnings)
220832f82f763185767d63ae4bf05021c5630c155fJordan Rose
230832f82f763185767d63ae4bf05021c5630c155fJordan Roseusing namespace clang;
24e7427636767501903cfa51ccecafa7a4795a23c2Jordan Roseusing namespace diagtool;
250832f82f763185767d63ae4bf05021c5630c155fJordan Rose
260832f82f763185767d63ae4bf05021c5630c155fJordan Rosenamespace {
270832f82f763185767d63ae4bf05021c5630c155fJordan Rose  struct PrettyDiag {
280832f82f763185767d63ae4bf05021c5630c155fJordan Rose    StringRef Name;
290832f82f763185767d63ae4bf05021c5630c155fJordan Rose    StringRef Flag;
300832f82f763185767d63ae4bf05021c5630c155fJordan Rose    DiagnosticsEngine::Level Level;
310832f82f763185767d63ae4bf05021c5630c155fJordan Rose
320832f82f763185767d63ae4bf05021c5630c155fJordan Rose    PrettyDiag(StringRef name, StringRef flag, DiagnosticsEngine::Level level)
330832f82f763185767d63ae4bf05021c5630c155fJordan Rose    : Name(name), Flag(flag), Level(level) {}
340832f82f763185767d63ae4bf05021c5630c155fJordan Rose
350832f82f763185767d63ae4bf05021c5630c155fJordan Rose    bool operator<(const PrettyDiag &x) const { return Name < x.Name; }
360832f82f763185767d63ae4bf05021c5630c155fJordan Rose  };
370832f82f763185767d63ae4bf05021c5630c155fJordan Rose}
380832f82f763185767d63ae4bf05021c5630c155fJordan Rose
390832f82f763185767d63ae4bf05021c5630c155fJordan Rosestatic void printUsage() {
400832f82f763185767d63ae4bf05021c5630c155fJordan Rose  llvm::errs() << "Usage: diagtool show-enabled [<flags>] <single-input.c>\n";
410832f82f763185767d63ae4bf05021c5630c155fJordan Rose}
420832f82f763185767d63ae4bf05021c5630c155fJordan Rose
430832f82f763185767d63ae4bf05021c5630c155fJordan Rosestatic char getCharForLevel(DiagnosticsEngine::Level Level) {
440832f82f763185767d63ae4bf05021c5630c155fJordan Rose  switch (Level) {
450832f82f763185767d63ae4bf05021c5630c155fJordan Rose  case DiagnosticsEngine::Ignored: return ' ';
460832f82f763185767d63ae4bf05021c5630c155fJordan Rose  case DiagnosticsEngine::Note:    return '-';
47651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case DiagnosticsEngine::Remark:  return 'R';
480832f82f763185767d63ae4bf05021c5630c155fJordan Rose  case DiagnosticsEngine::Warning: return 'W';
490832f82f763185767d63ae4bf05021c5630c155fJordan Rose  case DiagnosticsEngine::Error:   return 'E';
500832f82f763185767d63ae4bf05021c5630c155fJordan Rose  case DiagnosticsEngine::Fatal:   return 'F';
510832f82f763185767d63ae4bf05021c5630c155fJordan Rose  }
520832f82f763185767d63ae4bf05021c5630c155fJordan Rose
530832f82f763185767d63ae4bf05021c5630c155fJordan Rose  llvm_unreachable("Unknown diagnostic level");
540832f82f763185767d63ae4bf05021c5630c155fJordan Rose}
550832f82f763185767d63ae4bf05021c5630c155fJordan Rose
560832f82f763185767d63ae4bf05021c5630c155fJordan Rosestatic IntrusiveRefCntPtr<DiagnosticsEngine>
570832f82f763185767d63ae4bf05021c5630c155fJordan RosecreateDiagnostics(unsigned int argc, char **argv) {
580832f82f763185767d63ae4bf05021c5630c155fJordan Rose  IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs());
590832f82f763185767d63ae4bf05021c5630c155fJordan Rose
600832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // Buffer diagnostics from argument parsing so that we can output them using a
610832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // well formed diagnostic object.
620832f82f763185767d63ae4bf05021c5630c155fJordan Rose  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
630832f82f763185767d63ae4bf05021c5630c155fJordan Rose  IntrusiveRefCntPtr<DiagnosticsEngine> InterimDiags(
6402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor    new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer));
650832f82f763185767d63ae4bf05021c5630c155fJordan Rose
660832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // Try to build a CompilerInvocation.
67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<CompilerInvocation> Invocation(
68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      createInvocationFromCommandLine(ArrayRef<const char *>(argv, argc),
69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                      InterimDiags));
700832f82f763185767d63ae4bf05021c5630c155fJordan Rose  if (!Invocation)
71ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return nullptr;
720832f82f763185767d63ae4bf05021c5630c155fJordan Rose
730832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // Build the diagnostics parser
740832f82f763185767d63ae4bf05021c5630c155fJordan Rose  IntrusiveRefCntPtr<DiagnosticsEngine> FinalDiags =
75d47afb96a3f988e6d21a92fe4dfe875ab227c7c0Sean Silva    CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts());
760832f82f763185767d63ae4bf05021c5630c155fJordan Rose  if (!FinalDiags)
77ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return nullptr;
78ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
790832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // Flush any errors created when initializing everything. This could happen
800832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // for invalid command lines, which will probably give non-sensical results.
810832f82f763185767d63ae4bf05021c5630c155fJordan Rose  DiagsBuffer->FlushDiagnostics(*FinalDiags);
820832f82f763185767d63ae4bf05021c5630c155fJordan Rose
830832f82f763185767d63ae4bf05021c5630c155fJordan Rose  return FinalDiags;
840832f82f763185767d63ae4bf05021c5630c155fJordan Rose}
850832f82f763185767d63ae4bf05021c5630c155fJordan Rose
860832f82f763185767d63ae4bf05021c5630c155fJordan Roseint ShowEnabledWarnings::run(unsigned int argc, char **argv, raw_ostream &Out) {
870832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // First check our one flag (--levels).
880832f82f763185767d63ae4bf05021c5630c155fJordan Rose  bool ShouldShowLevels = true;
890832f82f763185767d63ae4bf05021c5630c155fJordan Rose  if (argc > 0) {
900832f82f763185767d63ae4bf05021c5630c155fJordan Rose    StringRef FirstArg(*argv);
910832f82f763185767d63ae4bf05021c5630c155fJordan Rose    if (FirstArg.equals("--no-levels")) {
920832f82f763185767d63ae4bf05021c5630c155fJordan Rose      ShouldShowLevels = false;
930832f82f763185767d63ae4bf05021c5630c155fJordan Rose      --argc;
940832f82f763185767d63ae4bf05021c5630c155fJordan Rose      ++argv;
950832f82f763185767d63ae4bf05021c5630c155fJordan Rose    } else if (FirstArg.equals("--levels")) {
960832f82f763185767d63ae4bf05021c5630c155fJordan Rose      ShouldShowLevels = true;
970832f82f763185767d63ae4bf05021c5630c155fJordan Rose      --argc;
980832f82f763185767d63ae4bf05021c5630c155fJordan Rose      ++argv;
990832f82f763185767d63ae4bf05021c5630c155fJordan Rose    }
1000832f82f763185767d63ae4bf05021c5630c155fJordan Rose  }
1010832f82f763185767d63ae4bf05021c5630c155fJordan Rose
1020832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // Create the diagnostic engine.
1030832f82f763185767d63ae4bf05021c5630c155fJordan Rose  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = createDiagnostics(argc, argv);
1040832f82f763185767d63ae4bf05021c5630c155fJordan Rose  if (!Diags) {
1050832f82f763185767d63ae4bf05021c5630c155fJordan Rose    printUsage();
1060832f82f763185767d63ae4bf05021c5630c155fJordan Rose    return EXIT_FAILURE;
1070832f82f763185767d63ae4bf05021c5630c155fJordan Rose  }
1080832f82f763185767d63ae4bf05021c5630c155fJordan Rose
1090832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // Now we have our diagnostics. Iterate through EVERY diagnostic and see
1100832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // which ones are turned on.
1110832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // FIXME: It would be very nice to print which flags are turning on which
1120832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // diagnostics, but this can be done with a diff.
113e7427636767501903cfa51ccecafa7a4795a23c2Jordan Rose  ArrayRef<DiagnosticRecord> AllDiagnostics = getBuiltinDiagnosticsByName();
1140832f82f763185767d63ae4bf05021c5630c155fJordan Rose  std::vector<PrettyDiag> Active;
1150832f82f763185767d63ae4bf05021c5630c155fJordan Rose
116e7427636767501903cfa51ccecafa7a4795a23c2Jordan Rose  for (ArrayRef<DiagnosticRecord>::iterator I = AllDiagnostics.begin(),
117e7427636767501903cfa51ccecafa7a4795a23c2Jordan Rose                                            E = AllDiagnostics.end();
118e7427636767501903cfa51ccecafa7a4795a23c2Jordan Rose       I != E; ++I) {
1190832f82f763185767d63ae4bf05021c5630c155fJordan Rose    unsigned DiagID = I->DiagID;
1200832f82f763185767d63ae4bf05021c5630c155fJordan Rose
1210832f82f763185767d63ae4bf05021c5630c155fJordan Rose    if (DiagnosticIDs::isBuiltinNote(DiagID))
1220832f82f763185767d63ae4bf05021c5630c155fJordan Rose      continue;
1230832f82f763185767d63ae4bf05021c5630c155fJordan Rose
1240832f82f763185767d63ae4bf05021c5630c155fJordan Rose    if (!DiagnosticIDs::isBuiltinWarningOrExtension(DiagID))
1250832f82f763185767d63ae4bf05021c5630c155fJordan Rose      continue;
1260832f82f763185767d63ae4bf05021c5630c155fJordan Rose
1270832f82f763185767d63ae4bf05021c5630c155fJordan Rose    DiagnosticsEngine::Level DiagLevel =
1280832f82f763185767d63ae4bf05021c5630c155fJordan Rose      Diags->getDiagnosticLevel(DiagID, SourceLocation());
1290832f82f763185767d63ae4bf05021c5630c155fJordan Rose    if (DiagLevel == DiagnosticsEngine::Ignored)
1300832f82f763185767d63ae4bf05021c5630c155fJordan Rose      continue;
1310832f82f763185767d63ae4bf05021c5630c155fJordan Rose
1320832f82f763185767d63ae4bf05021c5630c155fJordan Rose    StringRef WarningOpt = DiagnosticIDs::getWarningOptionForDiag(DiagID);
1330832f82f763185767d63ae4bf05021c5630c155fJordan Rose    Active.push_back(PrettyDiag(I->getName(), WarningOpt, DiagLevel));
1340832f82f763185767d63ae4bf05021c5630c155fJordan Rose  }
1350832f82f763185767d63ae4bf05021c5630c155fJordan Rose
1360832f82f763185767d63ae4bf05021c5630c155fJordan Rose  // Print them all out.
1370832f82f763185767d63ae4bf05021c5630c155fJordan Rose  for (std::vector<PrettyDiag>::const_iterator I = Active.begin(),
1380832f82f763185767d63ae4bf05021c5630c155fJordan Rose       E = Active.end(); I != E; ++I) {
1390832f82f763185767d63ae4bf05021c5630c155fJordan Rose    if (ShouldShowLevels)
1400832f82f763185767d63ae4bf05021c5630c155fJordan Rose      Out << getCharForLevel(I->Level) << "  ";
1410832f82f763185767d63ae4bf05021c5630c155fJordan Rose    Out << I->Name;
1420832f82f763185767d63ae4bf05021c5630c155fJordan Rose    if (!I->Flag.empty())
1430832f82f763185767d63ae4bf05021c5630c155fJordan Rose      Out << " [-W" << I->Flag << "]";
1440832f82f763185767d63ae4bf05021c5630c155fJordan Rose    Out << '\n';
1450832f82f763185767d63ae4bf05021c5630c155fJordan Rose  }
1460832f82f763185767d63ae4bf05021c5630c155fJordan Rose
1470832f82f763185767d63ae4bf05021c5630c155fJordan Rose  return EXIT_SUCCESS;
1480832f82f763185767d63ae4bf05021c5630c155fJordan Rose}
149