From: Chris Lattner Date: Wed, 15 Apr 2009 04:27:38 +0000 (+0000) Subject: refactor a bunch of the warning parsing stuff to simplify it. This removes the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5147e8e0186ec7d4c2c2aeb348c0354c1c3302f9;p=clang refactor a bunch of the warning parsing stuff to simplify it. This removes the -Wfoo=ignore syntax. GCC supports -Wno-foo, no need to invent our own stuff. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69136 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/clang-cc/Warnings.cpp b/tools/clang-cc/Warnings.cpp index 1dfe77abd9..e949c2e014 100644 --- a/tools/clang-cc/Warnings.cpp +++ b/tools/clang-cc/Warnings.cpp @@ -16,22 +16,13 @@ // 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 -// // 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-cc.h" #include "clang/Basic/Diagnostic.h" @@ -43,80 +34,23 @@ #include 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 OptionsList; - - OptionsList Options; - - struct WarningParser : public llvm::cl::basic_parser { - 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) { - fprintf(stderr, "Illegal warning option value: %s\n", - ArgValue.substr(Eq+1).c_str()); - return true; - } - } - return false; - } - }; -} - -static llvm::cl::list -OptWarnings("W", llvm::cl::location(Options), llvm::cl::Prefix); - -static llvm::cl::list > -OptWError("Werror", llvm::cl::location(Options), llvm::cl::CommaSeparated, - llvm::cl::ValueOptional); +// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The +// driver has stripped off -Wa,foo etc. +static llvm::cl::list +OptWarnings("W", llvm::cl::Prefix); static llvm::cl::opt OptPedantic("pedantic"); static llvm::cl::opt OptPedanticErrors("pedantic-errors"); static llvm::cl::opt OptNoWarnings("w"); -static llvm::cl::opt -OptWarnInSystemHeaders("Wsystem-headers", - llvm::cl::desc("Do not suppress warnings issued in system headers")); namespace { struct WarningOption { const char *Name; const diag::kind *Members; - size_t NumMembers; + unsigned NumMembers; }; } -#define DIAGS(a) a, (sizeof(a) / sizeof(a[0])) +#define DIAGS(a) a, unsigned(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 }; @@ -174,6 +108,7 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags) { Diags.setIgnoreAllWarnings(OptNoWarnings); Diags.setWarnOnExtensions(OptPedantic); Diags.setErrorOnExtensions(OptPedanticErrors); + Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers // Set some defaults that are currently set manually. This, too, should // be in the tablegen stuff later. @@ -189,48 +124,67 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags) { Diags.setDiagnosticMapping(diag::err_template_recursion_depth_exceeded, diag::MAP_FATAL); Diags.setDiagnosticMapping(diag::warn_missing_prototype, diag::MAP_IGNORE); - Diags.setSuppressSystemWarnings(!OptWarnInSystemHeaders); - - 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; + + // FIXME: -W -> -Wextra in driver. + // -fdiagnostics-show-option + + for (unsigned i = 0, e = OptWarnings.size(); i != e; ++i) { + const std::string &Opt = OptWarnings[i]; + const char *OptStart = &Opt[0]; + const char *OptEnd = OptStart+Opt.size(); + assert(*OptEnd == 0 && "Expect null termination for lower-bound search"); + + // Check to see if this warning starts with "no-", if so, this is a negative + // form of the option. + bool isPositive = true; + if (OptEnd-OptStart > 3 && memcmp(OptStart, "no-", 3) == 0) { + isPositive = false; + OptStart += 3; + } - case diag::MAP_ERROR: - Diags.setIgnoreAllWarnings(false); + // -Wsystem-headers is a special case, not driven by the option table. + if (OptEnd-OptStart == 14 && memcmp(OptStart, "system-headers", 14) == 0) { + Diags.setSuppressSystemWarnings(!isPositive); + continue; + } + + // -Werror/-Wno-error is a special case, not controlled by the option table. + // It also has the "specifier" form of -Werror=foo. + if (OptEnd-OptStart >= 5 && memcmp(OptStart, "error", 5) == 0) { + const char *Specifier = 0; + if (OptEnd-OptStart != 5) { // Specifier must be present. + if (OptStart[5] != '=' || OptEnd-OptStart == 6) { + fprintf(stderr, "Unknown warning option: -W%s\n", Opt.c_str()); + return true; + } + Specifier = OptStart+6; + } + + if (Specifier == 0) { Diags.setWarningsAsErrors(true); - break; + continue; } - continue; + + // FIXME: specifier not implemented yet + fprintf(stderr, "specifier in -W%s not supported yet\n", Opt.c_str()); + return true; } - WarningOption Key = { it->Name.c_str(), 0, 0 }; + + WarningOption Key = { OptStart, 0, 0 }; const WarningOption *Found = std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key, WarningOptionCompare); if (Found == OptionTable + OptionTableSize || strcmp(Found->Name, Key.Name) != 0) { - fprintf(stderr, "Unknown warning option: -W%s\n", Key.Name); + fprintf(stderr, "Unknown warning option: -W%s\n", Opt.c_str()); return true; } + diag::Mapping Mapping = isPositive ? diag::MAP_WARNING : diag::MAP_IGNORE; + // Option exists. - for (size_t i = 0, e = Found->NumMembers; i != e; ++i) - Diags.setDiagnosticMapping(Found->Members[i], it->Mapping); + for (unsigned i = 0, e = Found->NumMembers; i != e; ++i) + Diags.setDiagnosticMapping(Found->Members[i], Mapping); } return false; }