[cfe-commits] r66276 - in /cfe/trunk/Driver: CMakeLists.txt Warnings.cpp clang.cpp clang.h

Sebastian Redl sebastian.redl at getdesigned.at
Fri Mar 6 09:41:35 PST 2009


Author: cornedbee
Date: Fri Mar  6 11:41:35 2009
New Revision: 66276

URL: http://llvm.org/viewvc/llvm-project?rev=66276&view=rev
Log:
Implement the machinery that can process TableGenerated warning options.
Manually write a table and some ad-hoc code to provide feature parity with the current code.

Added:
    cfe/trunk/Driver/Warnings.cpp
Modified:
    cfe/trunk/Driver/CMakeLists.txt
    cfe/trunk/Driver/clang.cpp
    cfe/trunk/Driver/clang.h

Modified: cfe/trunk/Driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/CMakeLists.txt?rev=66276&r1=66275&r2=66276&view=diff

==============================================================================
--- cfe/trunk/Driver/CMakeLists.txt (original)
+++ cfe/trunk/Driver/CMakeLists.txt Fri Mar  6 11:41:35 2009
@@ -37,4 +37,5 @@
   RewriteObjC.cpp
   RewriteTest.cpp
   SerializationTest.cpp
+  Warnings.cpp
   )

Added: cfe/trunk/Driver/Warnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/Warnings.cpp?rev=66276&view=auto

==============================================================================
--- cfe/trunk/Driver/Warnings.cpp (added)
+++ cfe/trunk/Driver/Warnings.cpp Fri Mar  6 11:41:35 2009
@@ -0,0 +1,217 @@
+//===--- Warnings.cpp - C-Language Front-end ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Command line warning options handler.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is responsible for handling all warning options. This includes
+// a number of -Wfoo options and their variants, which are driven by TableGen-
+// generated data, and the special cases -pedantic, -pedantic-errors, -w and
+// -Werror.
+//
+// Warning options control the handling of the warnings that Clang emits. There
+// are three possible reactions to any given warning:
+// ignore: Do nothing
+// warn:   Emit a message, but don't fail the compilation
+// error:  Emit a message and fail the compilation
+//
+// Clang is parsed warning options. Each warning option controls any number of
+// actual warnings.
+// Given a warning option 'foo', the following are valid:
+// -Wfoo=ignore  -> Ignore the controlled warnings.
+// -Wfoo=warn    -> Warn about the controlled warnings.
+// -Wfoo=error   -> Fail on the controlled warnings.
+// -Wfoo         -> alias of -Wfoo=warn
+// -Wno-foo      -> alias of -Wfoo=ignore
+// -Werror=foo   -> alias of -Wfoo=error
+//
+// Because of this complex handling of options, the default parser is replaced.
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "llvm/Support/CommandLine.h"
+#include <vector>
+#include <string>
+#include <utility>
+#include <algorithm>
+#include <string.h>
+
+using namespace clang;
+
+namespace {
+  struct ParsedOption {
+    std::string Name;
+    diag::Mapping Mapping;
+
+    ParsedOption() {}
+    // Used by -Werror, implicitly.
+    ParsedOption(const std::string& name) : Name(name), Mapping(diag::MAP_ERROR)
+    {}
+  };
+
+  typedef std::vector<ParsedOption> OptionsList;
+
+  OptionsList Options;
+
+  struct WarningParser : public llvm::cl::basic_parser<ParsedOption> {
+    diag::Mapping StrToMapping(const std::string &S) {
+      if (S == "ignore")
+        return diag::MAP_IGNORE;
+      if (S == "warn")
+        return diag::MAP_WARNING;
+      if (S == "error")
+        return diag::MAP_ERROR;
+      return diag::MAP_DEFAULT;
+    }
+    bool parse(llvm::cl::Option &O, const char *ArgName,
+               const std::string &ArgValue, ParsedOption &Val)
+    {
+      size_t Eq = ArgValue.find("=");
+      if (Eq == std::string::npos) {
+        // Could be -Wfoo or -Wno-foo
+        if (ArgValue.compare(0, 3, "no-") == 0) {
+          Val.Name = ArgValue.substr(3);
+          Val.Mapping = diag::MAP_IGNORE;
+        } else {
+          Val.Name = ArgValue;
+          Val.Mapping = diag::MAP_WARNING;
+        }
+      } else {
+        Val.Name = ArgValue.substr(0, Eq);
+        Val.Mapping = StrToMapping(ArgValue.substr(Eq+1));
+        if (Val.Mapping == diag::MAP_DEFAULT)
+          return true;
+      }
+      return false;
+    }
+  };
+}
+
+static llvm::cl::list<ParsedOption, OptionsList, WarningParser>
+OptWarnings("W", llvm::cl::location(Options), llvm::cl::Prefix);
+
+static llvm::cl::list<ParsedOption, OptionsList, llvm::cl::parser<std::string> >
+OptWError("Werror", llvm::cl::location(Options), llvm::cl::CommaSeparated,
+          llvm::cl::ValueOptional);
+
+static llvm::cl::opt<bool> OptPedantic("pedantic");
+static llvm::cl::opt<bool> OptPedanticErrors("pedantic-errors");
+static llvm::cl::opt<bool> OptNoWarnings("w");
+static llvm::cl::opt<bool>
+OptSuppressSystemWarnings("suppress-system-warnings",
+                  llvm::cl::desc("Suppress warnings issued in system headers"),
+                          llvm::cl::init(true));
+
+namespace {
+  struct WarningOption {
+    const char *Name;
+    const diag::kind *Members;
+    size_t NumMembers;
+  };
+  bool operator <(const WarningOption& lhs, const WarningOption& rhs) {
+    return strcmp(lhs.Name, rhs.Name) < 0;
+  }
+}
+#define DIAGS(a) a, (sizeof(a) / sizeof(a[0]))
+// These tables will be TableGenerated later.
+// First the table sets describing the diagnostics controlled by each option.
+static const diag::kind UnusedMacrosDiags[] = { diag::pp_macro_not_used };
+static const diag::kind FloatEqualDiags[] = { diag::warn_floatingpoint_eq };
+static const diag::kind ReadOnlySetterAttrsDiags[] = {
+  diag::warn_objc_property_attr_mutually_exclusive
+};
+static const diag::kind FormatNonLiteralDiags[] = {
+  diag::warn_printf_not_string_constant
+};
+static const diag::kind UndefDiags[] = { diag::warn_pp_undef_identifier };
+static const diag::kind ImplicitFunctionDeclarationDiags[] = {
+  diag::ext_implicit_function_decl, diag::warn_implicit_function_decl
+};
+// Hmm ... this option is currently actually completely ignored.
+//static const diag::kind StrictSelectorMatchDiags[] = {  };
+// Second the table of options.  MUST be sorted by name! Binary lookup is done.
+static const WarningOption OptionTable[] = {
+  { "float-equal",           DIAGS(FloatEqualDiags) },
+  { "format-nonliteral",     DIAGS(FormatNonLiteralDiags) },
+  { "implicit-function-declaration", DIAGS(ImplicitFunctionDeclarationDiags) },
+  { "readonly-setter-attrs", DIAGS(ReadOnlySetterAttrsDiags) },
+  { "undef",                 DIAGS(UndefDiags) },
+  { "unused-macros",         DIAGS(UnusedMacrosDiags) },
+//  { "strict-selector-match", DIAGS(StrictSelectorMatchDiags) }
+};
+static const size_t OptionTableSize =
+  sizeof(OptionTable) / sizeof(OptionTable[0]);
+
+namespace clang {
+
+bool ProcessWarningOptions(Diagnostic &Diags) {
+  // FIXME: These should be mapped to group options.
+  Diags.setIgnoreAllWarnings(OptNoWarnings);
+  Diags.setWarnOnExtensions(OptPedantic);
+  Diags.setErrorOnExtensions(OptPedanticErrors);
+
+  // Set some defaults that are currently set manually. This, too, should
+  // be in the tablegen stuff later.
+  Diags.setDiagnosticMapping(diag::pp_macro_not_used, diag::MAP_IGNORE);
+  Diags.setDiagnosticMapping(diag::warn_floatingpoint_eq, diag::MAP_IGNORE);
+  Diags.setDiagnosticMapping(diag::warn_objc_property_attr_mutually_exclusive,
+                             diag::MAP_IGNORE);
+  Diags.setDiagnosticMapping(diag::warn_pp_undef_identifier, diag::MAP_IGNORE);
+  Diags.setDiagnosticMapping(diag::warn_implicit_function_decl,
+                             diag::MAP_IGNORE);
+
+  Diags.setDiagnosticMapping(diag::err_pp_file_not_found, diag::MAP_FATAL);
+  Diags.setSuppressSystemWarnings(OptSuppressSystemWarnings);
+
+  for (OptionsList::iterator it = Options.begin(), e = Options.end();
+      it != e; ++it) {
+    if (it->Name.empty()) {
+      // Empty string is "everything". This way, -Werror does the right thing.
+      // FIXME: These flags do not participate in proper option overriding.
+      switch(it->Mapping) {
+      default:
+        assert(false && "Illegal mapping");
+        break;
+
+      case diag::MAP_IGNORE:
+        Diags.setIgnoreAllWarnings(true);
+        Diags.setWarningsAsErrors(false);
+        break;
+
+      case diag::MAP_WARNING:
+        Diags.setIgnoreAllWarnings(false);
+        Diags.setWarningsAsErrors(false);
+        break;
+
+      case diag::MAP_ERROR:
+        Diags.setIgnoreAllWarnings(false);
+        Diags.setWarningsAsErrors(true);
+        break;
+      }
+      continue;
+    }
+    WarningOption Key = { it->Name.c_str(), 0, 0 };
+    const WarningOption *Found = std::lower_bound(OptionTable,
+                                                  OptionTable + OptionTableSize,
+                                                  Key);
+    if (Found == OptionTable + OptionTableSize ||
+        strcmp(Found->Name, Key.Name) != 0)
+      return true;
+
+    // Option exists.
+    for (size_t i = 0; i < Found->NumMembers; ++i) {
+      Diags.setDiagnosticMapping(Found->Members[i], it->Mapping);
+    }
+  }
+  return false;
+}
+
+}

Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=66276&r1=66275&r2=66276&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Fri Mar  6 11:41:35 2009
@@ -679,101 +679,6 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Our DiagnosticClient implementation
-//===----------------------------------------------------------------------===//
-
-// FIXME: Werror should take a list of things, -Werror=foo,bar
-static llvm::cl::opt<bool>
-WarningsAsErrors("Werror", llvm::cl::desc("Treat all warnings as errors"));
-
-static llvm::cl::opt<bool>
-SilenceWarnings("w", llvm::cl::desc("Do not emit any warnings"));
-
-static llvm::cl::opt<bool>
-WarnOnExtensions("pedantic", llvm::cl::init(false),
-                 llvm::cl::desc("Issue a warning on uses of GCC extensions"));
-
-static llvm::cl::opt<bool>
-ErrorOnExtensions("pedantic-errors",
-                  llvm::cl::desc("Issue an error on uses of GCC extensions"));
-
-static llvm::cl::opt<bool>
-SuppressSystemWarnings("suppress-system-warnings",
-                  llvm::cl::desc("Suppress warnings issued in system headers"),
-                       llvm::cl::init(true));
-
-static llvm::cl::opt<bool>
-WarnUnusedMacros("Wunused-macros",
-         llvm::cl::desc("Warn for unused macros in the main translation unit"));
-
-static llvm::cl::opt<bool>
-WarnFloatEqual("Wfloat-equal",
-   llvm::cl::desc("Warn about equality comparisons of floating point values"));
-
-static llvm::cl::opt<bool>
-WarnPropertyReadonlyAttrs("Wreadonly-setter-attrs",
-   llvm::cl::desc("Warn about readonly properties with writable attributes"));
-
-static llvm::cl::opt<bool>
-WarnNoFormatNonLiteral("Wno-format-nonliteral",
-   llvm::cl::desc("Do not warn about non-literal format strings"));
-
-static llvm::cl::opt<bool>
-WarnUndefMacros("Wundef",
-   llvm::cl::desc("Warn on use of undefined macros in #if's"));
-
-static llvm::cl::opt<bool>
-WarnImplicitFunctionDeclaration("Wimplicit-function-declaration",
-   llvm::cl::desc("Warn about uses of implicitly defined functions"));
-
-static llvm::cl::opt<bool>
-WarnNoStrictSelectorMatch("Wno-strict-selector-match",
-   llvm::cl::desc("Do not warn about duplicate methods that have the same size"
-                  " and alignment"),
-   llvm::cl::init(true));
-
-/// InitializeDiagnostics - Initialize the diagnostic object, based on the
-/// current command line option settings.
-static void InitializeDiagnostics(Diagnostic &Diags) {
-  Diags.setIgnoreAllWarnings(SilenceWarnings);
-  Diags.setWarningsAsErrors(WarningsAsErrors);
-  Diags.setWarnOnExtensions(WarnOnExtensions);
-  Diags.setErrorOnExtensions(ErrorOnExtensions);
-
-  // Suppress warnings in system headers unless requested not to.
-  Diags.setSuppressSystemWarnings(SuppressSystemWarnings);
-
-  // Silence the "macro is not used" warning unless requested.
-  if (!WarnUnusedMacros)
-    Diags.setDiagnosticMapping(diag::pp_macro_not_used, diag::MAP_IGNORE);
-               
-  // Silence "floating point comparison" warnings unless requested.
-  if (!WarnFloatEqual)
-    Diags.setDiagnosticMapping(diag::warn_floatingpoint_eq, diag::MAP_IGNORE);
-
-  if (!WarnPropertyReadonlyAttrs)
-    Diags.setDiagnosticMapping(diag::warn_objc_property_attr_mutually_exclusive,
-      diag::MAP_IGNORE);
-
-  // Silence "format string is not a string literal" warnings if requested
-  if (WarnNoFormatNonLiteral)
-    Diags.setDiagnosticMapping(diag::warn_printf_not_string_constant,
-                               diag::MAP_IGNORE);
-  if (!WarnUndefMacros)
-    Diags.setDiagnosticMapping(diag::warn_pp_undef_identifier,diag::MAP_IGNORE);
-    
-  if (WarnImplicitFunctionDeclaration)
-    Diags.setDiagnosticMapping(diag::ext_implicit_function_decl,
-                               diag::MAP_WARNING);
-  else
-    Diags.setDiagnosticMapping(diag::warn_implicit_function_decl,
-                               diag::MAP_IGNORE);
-  
-  
-  Diags.setDiagnosticMapping(diag::err_pp_file_not_found, diag::MAP_FATAL);
-}
-
-//===----------------------------------------------------------------------===//
 // Target Triple Processing.
 //===----------------------------------------------------------------------===//
 
@@ -1599,7 +1504,11 @@
   // Configure our handling of diagnostics.
   llvm::OwningPtr<DiagnosticClient> DiagClient(TextDiagClient);
   Diagnostic Diags(DiagClient.get());
-  InitializeDiagnostics(Diags);  
+  if (ProcessWarningOptions(Diags)) {
+    fprintf(stderr, "Error in warning options.\n");
+    return 1;
+  }
+  //InitializeDiagnostics(Diags);  
 
   // -I- is a deprecated GCC feature, scan for it and reject it.
   for (unsigned i = 0, e = I_dirs.size(); i != e; ++i) {

Modified: cfe/trunk/Driver/clang.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.h?rev=66276&r1=66275&r2=66276&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.h (original)
+++ cfe/trunk/Driver/clang.h Fri Mar  6 11:41:35 2009
@@ -26,6 +26,10 @@
 class IdentifierTable;
 class SourceManager;
 
+/// ProcessWarningOptions - Initialize the diagnostic client and process the
+/// warning options specified on the command line.
+bool ProcessWarningOptions(Diagnostic &Diags);
+
 /// DoPrintPreprocessedInput - Implement -E mode.
 void DoPrintPreprocessedInput(Preprocessor &PP, const std::string& OutFile);
 





More information about the cfe-commits mailing list