brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 13b8015 Raw
180 lines · cpp
1//===- TreeView.cpp - diagtool tool for printing warning 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/AllDiagnostics.h"12#include "clang/Basic/Diagnostic.h"13#include "clang/Basic/DiagnosticOptions.h"14#include "llvm/ADT/DenseSet.h"15#include "llvm/Support/Format.h"16#include "llvm/Support/Process.h"17 18DEF_DIAGTOOL("tree", "Show warning flags in a tree view", TreeView)19 20using namespace clang;21using namespace diagtool;22 23class TreePrinter {24  using Colors = llvm::raw_ostream::Colors;25 26public:27  llvm::raw_ostream &out;28  bool Internal;29 30  TreePrinter(llvm::raw_ostream &out) : out(out), Internal(false) {}31 32  static bool isIgnored(unsigned DiagID) {33    // FIXME: This feels like a hack.34    static DiagnosticOptions DiagOpts;35    static clang::DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts);36    return Diags.isIgnored(DiagID, SourceLocation());37  }38 39  static bool unimplemented(const GroupRecord &Group) {40    if (!Group.diagnostics().empty())41      return false;42 43    return llvm::all_of(Group.subgroups(), unimplemented);44  }45 46  static bool enabledByDefault(const GroupRecord &Group) {47    for (const DiagnosticRecord &DR : Group.diagnostics()) {48      if (isIgnored(DR.DiagID))49        return false;50    }51 52    for (const GroupRecord &GR : Group.subgroups()) {53      if (!enabledByDefault(GR))54        return false;55    }56 57    return true;58  }59 60  void printGroup(const GroupRecord &Group, unsigned Indent = 0) {61    out.indent(Indent * 2);62 63    if (unimplemented(Group))64      out << Colors::RED;65    else if (enabledByDefault(Group))66      out << Colors::GREEN;67    else68      out << Colors::YELLOW;69 70    out << "-W" << Group.getName() << "\n" << Colors::RESET;71 72    ++Indent;73    for (const GroupRecord &GR : Group.subgroups()) {74      printGroup(GR, Indent);75    }76 77    if (Internal) {78      for (const DiagnosticRecord &DR : Group.diagnostics()) {79        if (!isIgnored(DR.DiagID))80          out << Colors::GREEN;81        out.indent(Indent * 2);82        out << DR.getName() << Colors::RESET << "\n";83      }84    }85  }86 87  int showGroup(StringRef RootGroup) {88    ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();89 90    if (RootGroup.size() > UINT16_MAX) {91      llvm::errs() << "No such diagnostic group exists\n";92      return 1;93    }94 95    const GroupRecord *Found = llvm::lower_bound(AllGroups, RootGroup);96    if (Found == AllGroups.end() || Found->getName() != RootGroup) {97      llvm::errs() << "No such diagnostic group exists\n";98      return 1;99    }100 101    printGroup(*Found);102 103    return 0;104  }105 106  int showAll() {107    ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();108    llvm::DenseSet<unsigned> NonRootGroupIDs;109 110    for (const GroupRecord &GR : AllGroups) {111      for (auto SI = GR.subgroup_begin(), SE = GR.subgroup_end(); SI != SE;112           ++SI) {113        NonRootGroupIDs.insert((unsigned)SI.getID());114      }115    }116 117    assert(NonRootGroupIDs.size() < AllGroups.size());118 119    for (unsigned i = 0, e = AllGroups.size(); i != e; ++i) {120      if (!NonRootGroupIDs.count(i))121        printGroup(AllGroups[i]);122    }123 124    return 0;125  }126 127  void showKey() {128    out << '\n' << Colors::GREEN << "GREEN" << Colors::RESET129        << " = enabled by default";130    out << '\n'131        << Colors::YELLOW << "YELLOW" << Colors::RESET132        << " = disabled by default";133    out << '\n' << Colors::RED << "RED" << Colors::RESET134        << " = unimplemented (accepted for GCC compatibility)\n\n";135  }136};137 138static void printUsage() {139  llvm::errs() << "Usage: diagtool tree [--internal] [<diagnostic-group>]\n";140}141 142int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {143  // First check our one flag (--flags-only).144  bool Internal = false;145  if (argc > 0) {146    StringRef FirstArg(*argv);147    if (FirstArg == "--internal") {148      Internal = true;149      --argc;150      ++argv;151    }152  }153 154  bool ShowAll = false;155  StringRef RootGroup;156 157  switch (argc) {158  case 0:159    ShowAll = true;160    break;161  case 1:162    RootGroup = argv[0];163    RootGroup.consume_front("-W");164    if (RootGroup == "everything")165      ShowAll = true;166    // FIXME: Handle other special warning flags, like -pedantic.167    break;168  default:169    printUsage();170    return -1;171  }172 173  out.enable_colors(out.has_colors());174 175  TreePrinter TP(out);176  TP.Internal = Internal;177  TP.showKey();178  return ShowAll ? TP.showAll() : TP.showGroup(RootGroup);179}180