forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			148 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- 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;
 | |
| using namespace diagtool;
 | |
| 
 | |
| 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(
 | |
|     new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer));
 | |
| 
 | |
|   // 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 =
 | |
|     CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts());
 | |
|   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.
 | |
|   ArrayRef<DiagnosticRecord> AllDiagnostics = getBuiltinDiagnosticsByName();
 | |
|   std::vector<PrettyDiag> Active;
 | |
| 
 | |
|   for (ArrayRef<DiagnosticRecord>::iterator I = AllDiagnostics.begin(),
 | |
|                                             E = AllDiagnostics.end();
 | |
|        I != E; ++I) {
 | |
|     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;
 | |
| }
 |