[cfe-commits] r159093 - in /cfe/trunk: test/Misc/warning-flags-tree.c tools/diagtool/CMakeLists.txt tools/diagtool/DiagnosticNames.cpp tools/diagtool/DiagnosticNames.h tools/diagtool/ListWarnings.cpp tools/diagtool/ShowEnabledWarnings.cpp tools/diagtool/TreeView.cpp
Jordan Rose
jordan_rose at apple.com
Sat Jun 23 17:07:45 PDT 2012
Author: jrose
Date: Sat Jun 23 19:07:45 2012
New Revision: 159093
URL: http://llvm.org/viewvc/llvm-project?rev=159093&view=rev
Log:
[diagtool] Add a new "tree" command to shows warnings activated by a flag.
% diagtool tree -Wunused-value
-Wunused-value
-Wunused-comparison
warn_unused_comparison
-Wunused-result
warn_unused_result
warn_unused_call
warn_unused_container_subscript_expr
warn_unused_expr
warn_unused_property_expr
warn_unused_voidptr
Added:
cfe/trunk/test/Misc/warning-flags-tree.c
cfe/trunk/tools/diagtool/TreeView.cpp
Modified:
cfe/trunk/tools/diagtool/CMakeLists.txt
cfe/trunk/tools/diagtool/DiagnosticNames.cpp
cfe/trunk/tools/diagtool/DiagnosticNames.h
cfe/trunk/tools/diagtool/ListWarnings.cpp
cfe/trunk/tools/diagtool/ShowEnabledWarnings.cpp
Added: cfe/trunk/test/Misc/warning-flags-tree.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/warning-flags-tree.c?rev=159093&view=auto
==============================================================================
--- cfe/trunk/test/Misc/warning-flags-tree.c (added)
+++ cfe/trunk/test/Misc/warning-flags-tree.c Sat Jun 23 19:07:45 2012
@@ -0,0 +1,56 @@
+// RUN: diagtool tree | FileCheck -strict-whitespace %s
+// RUN: diagtool tree -Weverything | FileCheck -strict-whitespace %s
+// RUN: diagtool tree everything | FileCheck -strict-whitespace %s
+//
+// These three ways of running diagtool tree are the same:
+// they produce a tree for every top-level diagnostic flag.
+// Just check a few to make sure we're actually showing more than one group.
+//
+// CHECK: -W
+// CHECK: -Wextra
+// CHECK: -Wmissing-field-initializers
+// CHECK: warn_missing_field_initializers
+// CHECK: -Wall
+// CHECK: -Wmost
+
+// These flags are currently unimplemented; test that we output them anyway.
+// CHECK: -Wstrict-aliasing
+// CHECK-NEXT: -Wstrict-aliasing=0
+// CHECK-NEXT: -Wstrict-aliasing=1
+// CHECK-NEXT: -Wstrict-aliasing=2
+// CHECK: -Wstrict-overflow
+// CHECK-NEXT: -Wstrict-overflow=0
+// CHECK-NEXT: -Wstrict-overflow=1
+// CHECK-NEXT: -Wstrict-overflow=2
+// CHECK-NEXT: -Wstrict-overflow=3
+// CHECK-NEXT: -Wstrict-overflow=4
+// CHECK-NEXT: -Wstrict-overflow=5
+
+
+// RUN: not diagtool tree -Wthis-is-not-a-valid-flag
+
+
+// RUN: diagtool tree -Wgnu | FileCheck -strict-whitespace -check-prefix CHECK-GNU %s
+// CHECK-GNU: -Wgnu
+// CHECK-GNU: -Wgnu-designator
+// CHECK-GNU: ext_gnu_array_range
+// CHECK-GNU: ext_gnu_missing_equal_designator
+// CHECK-GNU: ext_gnu_old_style_field_designator
+// CHECK-GNU: -Wvla
+// CHECK-GNU: ext_vla
+// CHECK-GNU: ext_array_init_copy
+// CHECK-GNU: ext_empty_struct_union
+// CHECK-GNU: ext_expr_not_ice
+// There are more GNU extensions but we don't need to check them all.
+
+// RUN: diagtool tree --flags-only -Wgnu | FileCheck -check-prefix CHECK-FLAGS-ONLY %s
+// CHECK-FLAGS-ONLY: -Wgnu
+// CHECK-FLAGS-ONLY: -Wgnu-designator
+// CHECK-FLAGS-ONLY-NOT: ext_gnu_array_range
+// CHECK-FLAGS-ONLY-NOT: ext_gnu_missing_equal_designator
+// CHECK-FLAGS-ONLY-NOT: ext_gnu_old_style_field_designator
+// CHECK-FLAGS-ONLY: -Wvla
+// CHECK-FLAGS-ONLY-NOT: ext_vla
+// CHECK-FLAGS-ONLY-NOT: ext_array_init_copy
+// CHECK-FLAGS-ONLY-NOT: ext_empty_struct_union
+// CHECK-FLAGS-ONLY-NOT: ext_expr_not_ice
Modified: cfe/trunk/tools/diagtool/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/diagtool/CMakeLists.txt?rev=159093&r1=159092&r2=159093&view=diff
==============================================================================
--- cfe/trunk/tools/diagtool/CMakeLists.txt (original)
+++ cfe/trunk/tools/diagtool/CMakeLists.txt Sat Jun 23 19:07:45 2012
@@ -8,6 +8,7 @@
DiagnosticNames.cpp
ListWarnings.cpp
ShowEnabledWarnings.cpp
+ TreeView.cpp
)
add_dependencies(diagtool
Modified: cfe/trunk/tools/diagtool/DiagnosticNames.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/diagtool/DiagnosticNames.cpp?rev=159093&r1=159092&r2=159093&view=diff
==============================================================================
--- cfe/trunk/tools/diagtool/DiagnosticNames.cpp (original)
+++ cfe/trunk/tools/diagtool/DiagnosticNames.cpp Sat Jun 23 19:07:45 2012
@@ -9,17 +9,69 @@
#include "DiagnosticNames.h"
#include "clang/Basic/AllDiagnostics.h"
+#include "llvm/ADT/STLExtras.h"
using namespace clang;
+using namespace diagtool;
-const diagtool::DiagnosticRecord diagtool::BuiltinDiagnostics[] = {
+static const DiagnosticRecord BuiltinDiagnosticsByName[] = {
#define DIAG_NAME_INDEX(ENUM) { #ENUM, diag::ENUM, STR_SIZE(#ENUM, uint8_t) },
#include "clang/Basic/DiagnosticIndexName.inc"
#undef DIAG_NAME_INDEX
- { 0, 0, 0 }
};
-const size_t diagtool::BuiltinDiagnosticsCount =
- sizeof(diagtool::BuiltinDiagnostics) /
- sizeof(diagtool::BuiltinDiagnostics[0]) - 1;
+llvm::ArrayRef<DiagnosticRecord> diagtool::getBuiltinDiagnosticsByName() {
+ return BuiltinDiagnosticsByName;
+}
+
+// FIXME: Is it worth having two tables, especially when this one can get
+// out of sync easily?
+static const DiagnosticRecord BuiltinDiagnosticsByID[] = {
+#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \
+ SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER, \
+ CATEGORY) \
+ { #ENUM, diag::ENUM, STR_SIZE(#ENUM, uint8_t) },
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#undef DIAG
+};
+
+static bool orderByID(const DiagnosticRecord &Left,
+ const DiagnosticRecord &Right) {
+ return Left.DiagID < Right.DiagID;
+}
+
+const DiagnosticRecord &diagtool::getDiagnosticForID(short DiagID) {
+ DiagnosticRecord Key = {0, DiagID, 0};
+
+ const DiagnosticRecord *Result =
+ std::lower_bound(BuiltinDiagnosticsByID,
+ llvm::array_endof(BuiltinDiagnosticsByID),
+ Key, orderByID);
+ assert(Result && "diagnostic not found; table may be out of date");
+ return *Result;
+}
+
+
+#define GET_DIAG_ARRAYS
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_DIAG_ARRAYS
+
+// Second the table of options, sorted by name for fast binary lookup.
+static const GroupRecord OptionTable[] = {
+#define GET_DIAG_TABLE
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_DIAG_TABLE
+};
+
+llvm::ArrayRef<GroupRecord> diagtool::getDiagnosticGroups() {
+ return OptionTable;
+}
Modified: cfe/trunk/tools/diagtool/DiagnosticNames.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/diagtool/DiagnosticNames.h?rev=159093&r1=159092&r2=159093&view=diff
==============================================================================
--- cfe/trunk/tools/diagtool/DiagnosticNames.h (original)
+++ cfe/trunk/tools/diagtool/DiagnosticNames.h Sat Jun 23 19:07:45 2012
@@ -7,22 +7,122 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
namespace diagtool {
+
struct DiagnosticRecord {
const char *NameStr;
- unsigned short DiagID;
+ short DiagID;
uint8_t NameLen;
llvm::StringRef getName() const {
return llvm::StringRef(NameStr, NameLen);
}
+
+ bool operator<(const DiagnosticRecord &Other) const {
+ return getName() < Other.getName();
+ }
};
- extern const DiagnosticRecord BuiltinDiagnostics[];
- extern const size_t BuiltinDiagnosticsCount;
+ /// \brief Get every diagnostic in the system, sorted by name.
+ llvm::ArrayRef<DiagnosticRecord> getBuiltinDiagnosticsByName();
+
+ /// \brief Get a diagnostic by its ID.
+ const DiagnosticRecord &getDiagnosticForID(short DiagID);
+
+
+ struct GroupRecord {
+ // Be safe with the size of 'NameLen' because we don't statically check if
+ // the size will fit in the field; the struct size won't decrease with a
+ // shorter type anyway.
+ size_t NameLen;
+ const char *NameStr;
+ const short *Members;
+ const short *SubGroups;
+
+ llvm::StringRef getName() const {
+ return llvm::StringRef(NameStr, NameLen);
+ }
+
+ template<typename RecordType>
+ class group_iterator {
+ const short *CurrentID;
+
+ friend struct GroupRecord;
+ group_iterator(const short *Start) : CurrentID(Start) {
+ if (CurrentID && *CurrentID == -1)
+ CurrentID = 0;
+ }
+
+ public:
+ typedef RecordType value_type;
+ typedef const value_type & reference;
+ typedef const value_type * pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ inline reference operator*() const;
+ inline pointer operator->() const {
+ return &operator*();
+ }
+
+ inline short getID() const {
+ return *CurrentID;
+ }
+
+ group_iterator &operator++() {
+ ++CurrentID;
+ if (*CurrentID == -1)
+ CurrentID = 0;
+ return *this;
+ }
+
+ bool operator==(group_iterator &Other) const {
+ return CurrentID == Other.CurrentID;
+ }
+
+ bool operator!=(group_iterator &Other) const {
+ return CurrentID != Other.CurrentID;
+ }
+ };
+
+ typedef group_iterator<GroupRecord> subgroup_iterator;
+ subgroup_iterator subgroup_begin() const {
+ return SubGroups;
+ }
+ subgroup_iterator subgroup_end() const {
+ return 0;
+ }
+
+ typedef group_iterator<DiagnosticRecord> diagnostics_iterator;
+ diagnostics_iterator diagnostics_begin() const {
+ return Members;
+ }
+ diagnostics_iterator diagnostics_end() const {
+ return 0;
+ }
+
+ bool operator<(const GroupRecord &Other) const {
+ return getName() < Other.getName();
+ }
+ };
+
+ /// \brief Get every diagnostic group in the system, sorted by name.
+ llvm::ArrayRef<GroupRecord> getDiagnosticGroups();
+
+ template<>
+ inline GroupRecord::subgroup_iterator::reference
+ GroupRecord::subgroup_iterator::operator*() const {
+ return getDiagnosticGroups()[*CurrentID];
+ }
+ template<>
+ inline GroupRecord::diagnostics_iterator::reference
+ GroupRecord::diagnostics_iterator::operator*() const {
+ return getDiagnosticForID(*CurrentID);
+ }
} // end namespace diagtool
Modified: cfe/trunk/tools/diagtool/ListWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/diagtool/ListWarnings.cpp?rev=159093&r1=159092&r2=159093&view=diff
==============================================================================
--- cfe/trunk/tools/diagtool/ListWarnings.cpp (original)
+++ cfe/trunk/tools/diagtool/ListWarnings.cpp Sat Jun 23 19:07:45 2012
@@ -25,6 +25,7 @@
ListWarnings)
using namespace clang;
+using namespace diagtool;
namespace {
struct Entry {
@@ -52,9 +53,11 @@
std::vector<Entry> Flagged, Unflagged;
llvm::StringMap<std::vector<unsigned> > flagHistogram;
- for (const diagtool::DiagnosticRecord *di = diagtool::BuiltinDiagnostics,
- *de = di + diagtool::BuiltinDiagnosticsCount; di != de; ++di) {
-
+ ArrayRef<DiagnosticRecord> AllDiagnostics = getBuiltinDiagnosticsByName();
+
+ for (ArrayRef<DiagnosticRecord>::iterator di = AllDiagnostics.begin(),
+ de = AllDiagnostics.end();
+ di != de; ++di) {
unsigned diagID = di->DiagID;
if (DiagnosticIDs::isBuiltinNote(diagID))
@@ -74,9 +77,6 @@
}
}
- std::sort(Flagged.begin(), Flagged.end());
- std::sort(Unflagged.begin(), Unflagged.end());
-
out << "Warnings with flags (" << Flagged.size() << "):\n";
printEntries(Flagged, out);
Modified: cfe/trunk/tools/diagtool/ShowEnabledWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/diagtool/ShowEnabledWarnings.cpp?rev=159093&r1=159092&r2=159093&view=diff
==============================================================================
--- cfe/trunk/tools/diagtool/ShowEnabledWarnings.cpp (original)
+++ cfe/trunk/tools/diagtool/ShowEnabledWarnings.cpp Sat Jun 23 19:07:45 2012
@@ -21,6 +21,7 @@
ShowEnabledWarnings)
using namespace clang;
+using namespace diagtool;
namespace {
struct PrettyDiag {
@@ -109,10 +110,12 @@
// 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 (const diagtool::DiagnosticRecord *I = diagtool::BuiltinDiagnostics,
- *E = I + diagtool::BuiltinDiagnosticsCount; I != E; ++I) {
+ for (ArrayRef<DiagnosticRecord>::iterator I = AllDiagnostics.begin(),
+ E = AllDiagnostics.end();
+ I != E; ++I) {
unsigned DiagID = I->DiagID;
if (DiagnosticIDs::isBuiltinNote(DiagID))
@@ -130,8 +133,6 @@
Active.push_back(PrettyDiag(I->getName(), WarningOpt, DiagLevel));
}
- std::sort(Active.begin(), Active.end());
-
// Print them all out.
for (std::vector<PrettyDiag>::const_iterator I = Active.begin(),
E = Active.end(); I != E; ++I) {
Added: cfe/trunk/tools/diagtool/TreeView.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/diagtool/TreeView.cpp?rev=159093&view=auto
==============================================================================
--- cfe/trunk/tools/diagtool/TreeView.cpp (added)
+++ cfe/trunk/tools/diagtool/TreeView.cpp Sat Jun 23 19:07:45 2012
@@ -0,0 +1,135 @@
+//===- TreeView.cpp - diagtool tool for printing warning flags ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This diagnostic tool
+//
+//===----------------------------------------------------------------------===//
+
+#include "DiagTool.h"
+#include "DiagnosticNames.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/Format.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Basic/AllDiagnostics.h"
+
+DEF_DIAGTOOL("tree",
+ "Show warning flags in a tree view",
+ TreeView)
+
+using namespace clang;
+using namespace diagtool;
+
+static void printUsage() {
+ llvm::errs() << "Usage: diagtool tree [--flags-only] [<diagnostic-group>]\n";
+}
+
+static void printGroup(llvm::raw_ostream &out, const GroupRecord &Group,
+ bool FlagsOnly, unsigned Indent = 0) {
+ out.indent(Indent * 2);
+ out << "-W" << Group.getName() << "\n";
+
+ ++Indent;
+ for (GroupRecord::subgroup_iterator I = Group.subgroup_begin(),
+ E = Group.subgroup_end();
+ I != E; ++I) {
+ printGroup(out, *I, FlagsOnly, Indent);
+ }
+
+ if (!FlagsOnly) {
+ for (GroupRecord::diagnostics_iterator I = Group.diagnostics_begin(),
+ E = Group.diagnostics_end();
+ I != E; ++I) {
+ out.indent(Indent * 2);
+ out << I->getName() << "\n";
+ }
+ }
+}
+
+static int showGroup(llvm::raw_ostream &out, StringRef RootGroup,
+ bool FlagsOnly) {
+ ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
+
+ GroupRecord Key = { RootGroup.size(), RootGroup.data(), 0, 0 };
+ const GroupRecord *Found =
+ std::lower_bound(AllGroups.begin(), AllGroups.end(), Key);
+
+ if (Found == AllGroups.end() || Found->getName() != RootGroup) {
+ llvm::errs() << "No such diagnostic group exists\n";
+ return 1;
+ }
+
+ printGroup(out, *Found, FlagsOnly);
+
+ return 0;
+}
+
+static int showAll(llvm::raw_ostream &out, bool FlagsOnly) {
+ ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
+ llvm::DenseSet<unsigned> NonRootGroupIDs;
+
+ for (ArrayRef<GroupRecord>::iterator I = AllGroups.begin(),
+ E = AllGroups.end();
+ I != E; ++I) {
+ for (GroupRecord::subgroup_iterator SI = I->subgroup_begin(),
+ SE = I->subgroup_end();
+ SI != SE; ++SI) {
+ NonRootGroupIDs.insert((unsigned)SI.getID());
+ }
+ }
+
+ assert(NonRootGroupIDs.size() < AllGroups.size());
+
+ for (unsigned i = 0, e = AllGroups.size(); i != e; ++i) {
+ if (!NonRootGroupIDs.count(i))
+ printGroup(out, AllGroups[i], FlagsOnly);
+ }
+
+ return 0;
+}
+
+int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {
+ // First check our one flag (--flags-only).
+ bool FlagsOnly = false;
+ if (argc > 0) {
+ StringRef FirstArg(*argv);
+ if (FirstArg.equals("--flags-only")) {
+ FlagsOnly = true;
+ --argc;
+ ++argv;
+ }
+ }
+
+ bool ShowAll = false;
+ StringRef RootGroup;
+
+ switch (argc) {
+ case 0:
+ ShowAll = true;
+ break;
+ case 1:
+ RootGroup = argv[0];
+ if (RootGroup.startswith("-W"))
+ RootGroup = RootGroup.substr(2);
+ if (RootGroup == "everything")
+ ShowAll = true;
+ // FIXME: Handle other special warning flags, like -pedantic.
+ break;
+ default:
+ printUsage();
+ return -1;
+ }
+
+ if (ShowAll)
+ return showAll(out, FlagsOnly);
+
+ return showGroup(out, RootGroup, FlagsOnly);
+}
+
More information about the cfe-commits
mailing list