xref: /minix3/external/bsd/llvm/dist/clang/tools/diagtool/ShowEnabledWarnings.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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