brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 5b25e65 Raw
150 lines · cpp
1//===- ShowEnabledWarnings - diagtool tool for printing enabled flags -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DiagTool.h"10#include "DiagnosticNames.h"11#include "clang/Basic/LLVM.h"12#include "clang/Driver/CreateInvocationFromArgs.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#include "llvm/Support/VirtualFileSystem.h"19 20DEF_DIAGTOOL("show-enabled",21             "Show which warnings are enabled for a given command line",22             ShowEnabledWarnings)23 24using namespace clang;25using namespace diagtool;26 27namespace {28  struct PrettyDiag {29    StringRef Name;30    StringRef Flag;31    DiagnosticsEngine::Level Level;32 33    PrettyDiag(StringRef name, StringRef flag, DiagnosticsEngine::Level level)34    : Name(name), Flag(flag), Level(level) {}35 36    bool operator<(const PrettyDiag &x) const { return Name < x.Name; }37  };38}39 40static void printUsage() {41  llvm::errs() << "Usage: diagtool show-enabled [<flags>] <single-input.c>\n";42}43 44static char getCharForLevel(DiagnosticsEngine::Level Level) {45  switch (Level) {46  case DiagnosticsEngine::Ignored: return ' ';47  case DiagnosticsEngine::Note:    return '-';48  case DiagnosticsEngine::Remark:  return 'R';49  case DiagnosticsEngine::Warning: return 'W';50  case DiagnosticsEngine::Error:   return 'E';51  case DiagnosticsEngine::Fatal:   return 'F';52  }53 54  llvm_unreachable("Unknown diagnostic level");55}56 57static IntrusiveRefCntPtr<DiagnosticsEngine>58createDiagnostics(unsigned int argc, char **argv) {59  DiagnosticOptions DiagOpts;60 61  // Buffer diagnostics from argument parsing so that we can output them using a62  // well formed diagnostic object.63  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;64 65  // Try to build a CompilerInvocation.66  SmallVector<const char *, 4> Args;67  Args.push_back("diagtool");68  Args.append(argv, argv + argc);69  CreateInvocationOptions CIOpts;70  CIOpts.Diags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(71      DiagnosticIDs::create(), DiagOpts, DiagsBuffer);72  std::unique_ptr<CompilerInvocation> Invocation =73      createInvocation(Args, CIOpts);74  if (!Invocation)75    return nullptr;76 77  // Build the diagnostics parser78  IntrusiveRefCntPtr<DiagnosticsEngine> FinalDiags =79      CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(),80                                          Invocation->getDiagnosticOpts());81  if (!FinalDiags)82    return nullptr;83 84  // Flush any errors created when initializing everything. This could happen85  // for invalid command lines, which will probably give non-sensical results.86  DiagsBuffer->FlushDiagnostics(*FinalDiags);87 88  return FinalDiags;89}90 91int ShowEnabledWarnings::run(unsigned int argc, char **argv, raw_ostream &Out) {92  // First check our one flag (--levels).93  bool ShouldShowLevels = true;94  if (argc > 0) {95    StringRef FirstArg(*argv);96    if (FirstArg == "--no-levels") {97      ShouldShowLevels = false;98      --argc;99      ++argv;100    } else if (FirstArg == "--levels") {101      ShouldShowLevels = true;102      --argc;103      ++argv;104    }105  }106 107  // Create the diagnostic engine.108  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = createDiagnostics(argc, argv);109  if (!Diags) {110    printUsage();111    return EXIT_FAILURE;112  }113 114  // Now we have our diagnostics. Iterate through EVERY diagnostic and see115  // which ones are turned on.116  // FIXME: It would be very nice to print which flags are turning on which117  // diagnostics, but this can be done with a diff.118  std::vector<PrettyDiag> Active;119 120  for (const DiagnosticRecord &DR : getBuiltinDiagnosticsByName()) {121    unsigned DiagID = DR.DiagID;122 123    if (DiagnosticIDs{}.isNote(DiagID))124      continue;125 126    if (!DiagnosticIDs{}.isWarningOrExtension(DiagID))127      continue;128 129    DiagnosticsEngine::Level DiagLevel =130      Diags->getDiagnosticLevel(DiagID, SourceLocation());131    if (DiagLevel == DiagnosticsEngine::Ignored)132      continue;133 134    StringRef WarningOpt = DiagnosticIDs{}.getWarningOptionForDiag(DiagID);135    Active.push_back(PrettyDiag(DR.getName(), WarningOpt, DiagLevel));136  }137 138  // Print them all out.139  for (const PrettyDiag &PD : Active) {140    if (ShouldShowLevels)141      Out << getCharForLevel(PD.Level) << "  ";142    Out << PD.Name;143    if (!PD.Flag.empty())144      Out << " [-W" << PD.Flag << "]";145    Out << '\n';146  }147 148  return EXIT_SUCCESS;149}150