2012-06-05 00:57:50 +08:00
|
|
|
//===- ShowEnabledWarnings - diagtool tool for printing enabled flags -----===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "DiagTool.h"
|
|
|
|
#include "DiagnosticNames.h"
|
|
|
|
#include "clang/Basic/LLVM.h"
|
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
|
|
#include "clang/Frontend/TextDiagnosticBuffer.h"
|
|
|
|
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
|
|
|
#include "clang/Frontend/Utils.h"
|
|
|
|
#include "llvm/Support/TargetSelect.h"
|
|
|
|
|
|
|
|
DEF_DIAGTOOL("show-enabled",
|
|
|
|
"Show which warnings are enabled for a given command line",
|
|
|
|
ShowEnabledWarnings)
|
|
|
|
|
|
|
|
using namespace clang;
|
2012-06-24 08:07:45 +08:00
|
|
|
using namespace diagtool;
|
2012-06-05 00:57:50 +08:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
struct PrettyDiag {
|
|
|
|
StringRef Name;
|
|
|
|
StringRef Flag;
|
|
|
|
DiagnosticsEngine::Level Level;
|
|
|
|
|
|
|
|
PrettyDiag(StringRef name, StringRef flag, DiagnosticsEngine::Level level)
|
|
|
|
: Name(name), Flag(flag), Level(level) {}
|
|
|
|
|
|
|
|
bool operator<(const PrettyDiag &x) const { return Name < x.Name; }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printUsage() {
|
|
|
|
llvm::errs() << "Usage: diagtool show-enabled [<flags>] <single-input.c>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
static char getCharForLevel(DiagnosticsEngine::Level Level) {
|
|
|
|
switch (Level) {
|
|
|
|
case DiagnosticsEngine::Ignored: return ' ';
|
|
|
|
case DiagnosticsEngine::Note: return '-';
|
|
|
|
case DiagnosticsEngine::Warning: return 'W';
|
|
|
|
case DiagnosticsEngine::Error: return 'E';
|
|
|
|
case DiagnosticsEngine::Fatal: return 'F';
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Unknown diagnostic level");
|
|
|
|
}
|
|
|
|
|
|
|
|
static IntrusiveRefCntPtr<DiagnosticsEngine>
|
|
|
|
createDiagnostics(unsigned int argc, char **argv) {
|
|
|
|
IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs());
|
|
|
|
|
|
|
|
// Buffer diagnostics from argument parsing so that we can output them using a
|
|
|
|
// well formed diagnostic object.
|
|
|
|
TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
|
|
|
|
IntrusiveRefCntPtr<DiagnosticsEngine> InterimDiags(
|
2012-10-24 06:26:28 +08:00
|
|
|
new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer));
|
2012-06-05 00:57:50 +08:00
|
|
|
|
|
|
|
// Try to build a CompilerInvocation.
|
|
|
|
OwningPtr<CompilerInvocation> Invocation(
|
|
|
|
createInvocationFromCommandLine(ArrayRef<const char *>(argv, argc),
|
|
|
|
InterimDiags));
|
|
|
|
if (!Invocation)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// Build the diagnostics parser
|
|
|
|
IntrusiveRefCntPtr<DiagnosticsEngine> FinalDiags =
|
2013-01-20 09:58:28 +08:00
|
|
|
CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts());
|
2012-06-05 00:57:50 +08:00
|
|
|
if (!FinalDiags)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// Flush any errors created when initializing everything. This could happen
|
|
|
|
// for invalid command lines, which will probably give non-sensical results.
|
|
|
|
DiagsBuffer->FlushDiagnostics(*FinalDiags);
|
|
|
|
|
|
|
|
return FinalDiags;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ShowEnabledWarnings::run(unsigned int argc, char **argv, raw_ostream &Out) {
|
|
|
|
// First check our one flag (--levels).
|
|
|
|
bool ShouldShowLevels = true;
|
|
|
|
if (argc > 0) {
|
|
|
|
StringRef FirstArg(*argv);
|
|
|
|
if (FirstArg.equals("--no-levels")) {
|
|
|
|
ShouldShowLevels = false;
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
} else if (FirstArg.equals("--levels")) {
|
|
|
|
ShouldShowLevels = true;
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the diagnostic engine.
|
|
|
|
IntrusiveRefCntPtr<DiagnosticsEngine> Diags = createDiagnostics(argc, argv);
|
|
|
|
if (!Diags) {
|
|
|
|
printUsage();
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we have our diagnostics. Iterate through EVERY diagnostic and see
|
|
|
|
// 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.
|
2012-06-24 08:07:45 +08:00
|
|
|
ArrayRef<DiagnosticRecord> AllDiagnostics = getBuiltinDiagnosticsByName();
|
2012-06-05 00:57:50 +08:00
|
|
|
std::vector<PrettyDiag> Active;
|
|
|
|
|
2012-06-24 08:07:45 +08:00
|
|
|
for (ArrayRef<DiagnosticRecord>::iterator I = AllDiagnostics.begin(),
|
|
|
|
E = AllDiagnostics.end();
|
|
|
|
I != E; ++I) {
|
2012-06-05 00:57:50 +08:00
|
|
|
unsigned DiagID = I->DiagID;
|
|
|
|
|
|
|
|
if (DiagnosticIDs::isBuiltinNote(DiagID))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!DiagnosticIDs::isBuiltinWarningOrExtension(DiagID))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
DiagnosticsEngine::Level DiagLevel =
|
|
|
|
Diags->getDiagnosticLevel(DiagID, SourceLocation());
|
|
|
|
if (DiagLevel == DiagnosticsEngine::Ignored)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
StringRef WarningOpt = DiagnosticIDs::getWarningOptionForDiag(DiagID);
|
|
|
|
Active.push_back(PrettyDiag(I->getName(), WarningOpt, DiagLevel));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print them all out.
|
|
|
|
for (std::vector<PrettyDiag>::const_iterator I = Active.begin(),
|
|
|
|
E = Active.end(); I != E; ++I) {
|
|
|
|
if (ShouldShowLevels)
|
|
|
|
Out << getCharForLevel(I->Level) << " ";
|
|
|
|
Out << I->Name;
|
|
|
|
if (!I->Flag.empty())
|
|
|
|
Out << " [-W" << I->Flag << "]";
|
|
|
|
Out << '\n';
|
|
|
|
}
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|