1f4a2713aSLionel Sambuc //===- ShowEnabledWarnings - diagtool tool for printing enabled flags -----===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc
10f4a2713aSLionel Sambuc #include "DiagTool.h"
11f4a2713aSLionel Sambuc #include "DiagnosticNames.h"
12f4a2713aSLionel Sambuc #include "clang/Basic/LLVM.h"
13f4a2713aSLionel Sambuc #include "clang/Frontend/CompilerInstance.h"
14f4a2713aSLionel Sambuc #include "clang/Frontend/TextDiagnosticBuffer.h"
15f4a2713aSLionel Sambuc #include "clang/Frontend/TextDiagnosticPrinter.h"
16f4a2713aSLionel Sambuc #include "clang/Frontend/Utils.h"
17f4a2713aSLionel Sambuc #include "llvm/Support/TargetSelect.h"
18f4a2713aSLionel Sambuc
19f4a2713aSLionel Sambuc DEF_DIAGTOOL("show-enabled",
20f4a2713aSLionel Sambuc "Show which warnings are enabled for a given command line",
21f4a2713aSLionel Sambuc ShowEnabledWarnings)
22f4a2713aSLionel Sambuc
23f4a2713aSLionel Sambuc using namespace clang;
24f4a2713aSLionel Sambuc using namespace diagtool;
25f4a2713aSLionel Sambuc
26f4a2713aSLionel Sambuc namespace {
27f4a2713aSLionel Sambuc struct PrettyDiag {
28f4a2713aSLionel Sambuc StringRef Name;
29f4a2713aSLionel Sambuc StringRef Flag;
30f4a2713aSLionel Sambuc DiagnosticsEngine::Level Level;
31f4a2713aSLionel Sambuc
PrettyDiag__anona5740dfe0111::PrettyDiag32f4a2713aSLionel Sambuc PrettyDiag(StringRef name, StringRef flag, DiagnosticsEngine::Level level)
33f4a2713aSLionel Sambuc : Name(name), Flag(flag), Level(level) {}
34f4a2713aSLionel Sambuc
operator <__anona5740dfe0111::PrettyDiag35f4a2713aSLionel Sambuc bool operator<(const PrettyDiag &x) const { return Name < x.Name; }
36f4a2713aSLionel Sambuc };
37f4a2713aSLionel Sambuc }
38f4a2713aSLionel Sambuc
printUsage()39f4a2713aSLionel Sambuc static void printUsage() {
40f4a2713aSLionel Sambuc llvm::errs() << "Usage: diagtool show-enabled [<flags>] <single-input.c>\n";
41f4a2713aSLionel Sambuc }
42f4a2713aSLionel Sambuc
getCharForLevel(DiagnosticsEngine::Level Level)43f4a2713aSLionel Sambuc static char getCharForLevel(DiagnosticsEngine::Level Level) {
44f4a2713aSLionel Sambuc switch (Level) {
45f4a2713aSLionel Sambuc case DiagnosticsEngine::Ignored: return ' ';
46f4a2713aSLionel Sambuc case DiagnosticsEngine::Note: return '-';
47*0a6a1f1dSLionel Sambuc case DiagnosticsEngine::Remark: return 'R';
48f4a2713aSLionel Sambuc case DiagnosticsEngine::Warning: return 'W';
49f4a2713aSLionel Sambuc case DiagnosticsEngine::Error: return 'E';
50f4a2713aSLionel Sambuc case DiagnosticsEngine::Fatal: return 'F';
51f4a2713aSLionel Sambuc }
52f4a2713aSLionel Sambuc
53f4a2713aSLionel Sambuc llvm_unreachable("Unknown diagnostic level");
54f4a2713aSLionel Sambuc }
55f4a2713aSLionel Sambuc
56f4a2713aSLionel Sambuc static IntrusiveRefCntPtr<DiagnosticsEngine>
createDiagnostics(unsigned int argc,char ** argv)57f4a2713aSLionel Sambuc createDiagnostics(unsigned int argc, char **argv) {
58f4a2713aSLionel Sambuc IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs());
59f4a2713aSLionel Sambuc
60f4a2713aSLionel Sambuc // Buffer diagnostics from argument parsing so that we can output them using a
61f4a2713aSLionel Sambuc // well formed diagnostic object.
62f4a2713aSLionel Sambuc TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
63f4a2713aSLionel Sambuc IntrusiveRefCntPtr<DiagnosticsEngine> InterimDiags(
64f4a2713aSLionel Sambuc new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer));
65f4a2713aSLionel Sambuc
66f4a2713aSLionel Sambuc // Try to build a CompilerInvocation.
67*0a6a1f1dSLionel Sambuc std::unique_ptr<CompilerInvocation> Invocation(
68*0a6a1f1dSLionel Sambuc createInvocationFromCommandLine(llvm::makeArrayRef(argv, argc),
69f4a2713aSLionel Sambuc InterimDiags));
70f4a2713aSLionel Sambuc if (!Invocation)
71*0a6a1f1dSLionel Sambuc return nullptr;
72f4a2713aSLionel Sambuc
73f4a2713aSLionel Sambuc // Build the diagnostics parser
74f4a2713aSLionel Sambuc IntrusiveRefCntPtr<DiagnosticsEngine> FinalDiags =
75f4a2713aSLionel Sambuc CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts());
76f4a2713aSLionel Sambuc if (!FinalDiags)
77*0a6a1f1dSLionel Sambuc return nullptr;
78f4a2713aSLionel Sambuc
79f4a2713aSLionel Sambuc // Flush any errors created when initializing everything. This could happen
80f4a2713aSLionel Sambuc // for invalid command lines, which will probably give non-sensical results.
81f4a2713aSLionel Sambuc DiagsBuffer->FlushDiagnostics(*FinalDiags);
82f4a2713aSLionel Sambuc
83f4a2713aSLionel Sambuc return FinalDiags;
84f4a2713aSLionel Sambuc }
85f4a2713aSLionel Sambuc
run(unsigned int argc,char ** argv,raw_ostream & Out)86f4a2713aSLionel Sambuc int ShowEnabledWarnings::run(unsigned int argc, char **argv, raw_ostream &Out) {
87f4a2713aSLionel Sambuc // First check our one flag (--levels).
88f4a2713aSLionel Sambuc bool ShouldShowLevels = true;
89f4a2713aSLionel Sambuc if (argc > 0) {
90f4a2713aSLionel Sambuc StringRef FirstArg(*argv);
91f4a2713aSLionel Sambuc if (FirstArg.equals("--no-levels")) {
92f4a2713aSLionel Sambuc ShouldShowLevels = false;
93f4a2713aSLionel Sambuc --argc;
94f4a2713aSLionel Sambuc ++argv;
95f4a2713aSLionel Sambuc } else if (FirstArg.equals("--levels")) {
96f4a2713aSLionel Sambuc ShouldShowLevels = true;
97f4a2713aSLionel Sambuc --argc;
98f4a2713aSLionel Sambuc ++argv;
99f4a2713aSLionel Sambuc }
100f4a2713aSLionel Sambuc }
101f4a2713aSLionel Sambuc
102f4a2713aSLionel Sambuc // Create the diagnostic engine.
103f4a2713aSLionel Sambuc IntrusiveRefCntPtr<DiagnosticsEngine> Diags = createDiagnostics(argc, argv);
104f4a2713aSLionel Sambuc if (!Diags) {
105f4a2713aSLionel Sambuc printUsage();
106f4a2713aSLionel Sambuc return EXIT_FAILURE;
107f4a2713aSLionel Sambuc }
108f4a2713aSLionel Sambuc
109f4a2713aSLionel Sambuc // Now we have our diagnostics. Iterate through EVERY diagnostic and see
110f4a2713aSLionel Sambuc // which ones are turned on.
111f4a2713aSLionel Sambuc // FIXME: It would be very nice to print which flags are turning on which
112f4a2713aSLionel Sambuc // diagnostics, but this can be done with a diff.
113f4a2713aSLionel Sambuc ArrayRef<DiagnosticRecord> AllDiagnostics = getBuiltinDiagnosticsByName();
114f4a2713aSLionel Sambuc std::vector<PrettyDiag> Active;
115f4a2713aSLionel Sambuc
116f4a2713aSLionel Sambuc for (ArrayRef<DiagnosticRecord>::iterator I = AllDiagnostics.begin(),
117f4a2713aSLionel Sambuc E = AllDiagnostics.end();
118f4a2713aSLionel Sambuc I != E; ++I) {
119f4a2713aSLionel Sambuc unsigned DiagID = I->DiagID;
120f4a2713aSLionel Sambuc
121f4a2713aSLionel Sambuc if (DiagnosticIDs::isBuiltinNote(DiagID))
122f4a2713aSLionel Sambuc continue;
123f4a2713aSLionel Sambuc
124f4a2713aSLionel Sambuc if (!DiagnosticIDs::isBuiltinWarningOrExtension(DiagID))
125f4a2713aSLionel Sambuc continue;
126f4a2713aSLionel Sambuc
127f4a2713aSLionel Sambuc DiagnosticsEngine::Level DiagLevel =
128f4a2713aSLionel Sambuc Diags->getDiagnosticLevel(DiagID, SourceLocation());
129f4a2713aSLionel Sambuc if (DiagLevel == DiagnosticsEngine::Ignored)
130f4a2713aSLionel Sambuc continue;
131f4a2713aSLionel Sambuc
132f4a2713aSLionel Sambuc StringRef WarningOpt = DiagnosticIDs::getWarningOptionForDiag(DiagID);
133f4a2713aSLionel Sambuc Active.push_back(PrettyDiag(I->getName(), WarningOpt, DiagLevel));
134f4a2713aSLionel Sambuc }
135f4a2713aSLionel Sambuc
136f4a2713aSLionel Sambuc // Print them all out.
137f4a2713aSLionel Sambuc for (std::vector<PrettyDiag>::const_iterator I = Active.begin(),
138f4a2713aSLionel Sambuc E = Active.end(); I != E; ++I) {
139f4a2713aSLionel Sambuc if (ShouldShowLevels)
140f4a2713aSLionel Sambuc Out << getCharForLevel(I->Level) << " ";
141f4a2713aSLionel Sambuc Out << I->Name;
142f4a2713aSLionel Sambuc if (!I->Flag.empty())
143f4a2713aSLionel Sambuc Out << " [-W" << I->Flag << "]";
144f4a2713aSLionel Sambuc Out << '\n';
145f4a2713aSLionel Sambuc }
146f4a2713aSLionel Sambuc
147f4a2713aSLionel Sambuc return EXIT_SUCCESS;
148f4a2713aSLionel Sambuc }
149