1 //===- ShowEnabledWarnings - diagtool tool for printing enabled flags -----===//
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-exception
7 //===----------------------------------------------------------------------===//
10 #include "DiagnosticNames.h"
11 #include "clang/Basic/LLVM.h"
12 #include "clang/Frontend/CompilerInstance.h"
13 #include "clang/Frontend/TextDiagnosticBuffer.h"
14 #include "clang/Frontend/TextDiagnosticPrinter.h"
15 #include "clang/Frontend/Utils.h"
16 #include "llvm/Support/TargetSelect.h"
18 DEF_DIAGTOOL("show-enabled",
19 "Show which warnings are enabled for a given command line",
22 using namespace clang
;
23 using namespace diagtool
;
29 DiagnosticsEngine::Level Level
;
31 PrettyDiag(StringRef name
, StringRef flag
, DiagnosticsEngine::Level level
)
32 : Name(name
), Flag(flag
), Level(level
) {}
34 bool operator<(const PrettyDiag
&x
) const { return Name
< x
.Name
; }
38 static void printUsage() {
39 llvm::errs() << "Usage: diagtool show-enabled [<flags>] <single-input.c>\n";
42 static char getCharForLevel(DiagnosticsEngine::Level Level
) {
44 case DiagnosticsEngine::Ignored
: return ' ';
45 case DiagnosticsEngine::Note
: return '-';
46 case DiagnosticsEngine::Remark
: return 'R';
47 case DiagnosticsEngine::Warning
: return 'W';
48 case DiagnosticsEngine::Error
: return 'E';
49 case DiagnosticsEngine::Fatal
: return 'F';
52 llvm_unreachable("Unknown diagnostic level");
55 static IntrusiveRefCntPtr
<DiagnosticsEngine
>
56 createDiagnostics(unsigned int argc
, char **argv
) {
57 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagIDs(new DiagnosticIDs());
59 // Buffer diagnostics from argument parsing so that we can output them using a
60 // well formed diagnostic object.
61 TextDiagnosticBuffer
*DiagsBuffer
= new TextDiagnosticBuffer
;
63 // Try to build a CompilerInvocation.
64 SmallVector
<const char *, 4> Args
;
65 Args
.push_back("diagtool");
66 Args
.append(argv
, argv
+ argc
);
67 CreateInvocationOptions CIOpts
;
69 new DiagnosticsEngine(DiagIDs
, new DiagnosticOptions(), DiagsBuffer
);
70 std::unique_ptr
<CompilerInvocation
> Invocation
=
71 createInvocation(Args
, CIOpts
);
75 // Build the diagnostics parser
76 IntrusiveRefCntPtr
<DiagnosticsEngine
> FinalDiags
=
77 CompilerInstance::createDiagnostics(&Invocation
->getDiagnosticOpts());
81 // Flush any errors created when initializing everything. This could happen
82 // for invalid command lines, which will probably give non-sensical results.
83 DiagsBuffer
->FlushDiagnostics(*FinalDiags
);
88 int ShowEnabledWarnings::run(unsigned int argc
, char **argv
, raw_ostream
&Out
) {
89 // First check our one flag (--levels).
90 bool ShouldShowLevels
= true;
92 StringRef
FirstArg(*argv
);
93 if (FirstArg
.equals("--no-levels")) {
94 ShouldShowLevels
= false;
97 } else if (FirstArg
.equals("--levels")) {
98 ShouldShowLevels
= true;
104 // Create the diagnostic engine.
105 IntrusiveRefCntPtr
<DiagnosticsEngine
> Diags
= createDiagnostics(argc
, argv
);
111 // Now we have our diagnostics. Iterate through EVERY diagnostic and see
112 // which ones are turned on.
113 // FIXME: It would be very nice to print which flags are turning on which
114 // diagnostics, but this can be done with a diff.
115 std::vector
<PrettyDiag
> Active
;
117 for (const DiagnosticRecord
&DR
: getBuiltinDiagnosticsByName()) {
118 unsigned DiagID
= DR
.DiagID
;
120 if (DiagnosticIDs::isBuiltinNote(DiagID
))
123 if (!DiagnosticIDs::isBuiltinWarningOrExtension(DiagID
))
126 DiagnosticsEngine::Level DiagLevel
=
127 Diags
->getDiagnosticLevel(DiagID
, SourceLocation());
128 if (DiagLevel
== DiagnosticsEngine::Ignored
)
131 StringRef WarningOpt
= DiagnosticIDs::getWarningOptionForDiag(DiagID
);
132 Active
.push_back(PrettyDiag(DR
.getName(), WarningOpt
, DiagLevel
));
135 // Print them all out.
136 for (const PrettyDiag
&PD
: Active
) {
137 if (ShouldShowLevels
)
138 Out
<< getCharForLevel(PD
.Level
) << " ";
140 if (!PD
.Flag
.empty())
141 Out
<< " [-W" << PD
.Flag
<< "]";