1193326Sed//===--- Warnings.cpp - C-Language Front-end ------------------------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// Command line warning options handler. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed// 14193326Sed// This file is responsible for handling all warning options. This includes 15193326Sed// a number of -Wfoo options and their variants, which are driven by TableGen- 16201361Srdivacky// generated data, and the special cases -pedantic, -pedantic-errors, -w, 17201361Srdivacky// -Werror and -Wfatal-errors. 18193326Sed// 19193326Sed// Each warning option controls any number of actual warnings. 20193326Sed// Given a warning option 'foo', the following are valid: 21201361Srdivacky// -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo 22193326Sed// 23193326Sed#include "clang/Frontend/Utils.h" 24193326Sed#include "clang/Basic/Diagnostic.h" 25243830Sdim#include "clang/Basic/DiagnosticOptions.h" 26194711Sed#include "clang/Frontend/FrontendDiagnostic.h" 27249423Sdim#include "clang/Lex/LexDiagnostic.h" 28249423Sdim#include "clang/Sema/SemaDiagnostic.h" 29249423Sdim#include <algorithm> 30193326Sed#include <cstring> 31193326Sed#include <utility> 32193326Sedusing namespace clang; 33193326Sed 34234353Sdim// EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning 35234353Sdim// opts 36234353Sdimstatic void EmitUnknownDiagWarning(DiagnosticsEngine &Diags, 37234353Sdim StringRef Prefix, StringRef Opt, 38234353Sdim bool isPositive) { 39234353Sdim StringRef Suggestion = DiagnosticIDs::getNearestWarningOption(Opt); 40234353Sdim if (!Suggestion.empty()) 41234353Sdim Diags.Report(isPositive? diag::warn_unknown_warning_option_suggest : 42234353Sdim diag::warn_unknown_negative_warning_option_suggest) 43234353Sdim << (Prefix.str() += Opt) << (Prefix.str() += Suggestion); 44234353Sdim else 45234353Sdim Diags.Report(isPositive? diag::warn_unknown_warning_option : 46234353Sdim diag::warn_unknown_negative_warning_option) 47234353Sdim << (Prefix.str() += Opt); 48234353Sdim} 49234353Sdim 50226633Sdimvoid clang::ProcessWarningOptions(DiagnosticsEngine &Diags, 51249423Sdim const DiagnosticOptions &Opts, 52249423Sdim bool ReportDiags) { 53193326Sed Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers 54199482Srdivacky Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings); 55243830Sdim Diags.setShowOverloads(Opts.getShowOverloads()); 56239462Sdim 57239462Sdim Diags.setElideType(Opts.ElideType); 58239462Sdim Diags.setPrintTemplateTree(Opts.ShowTemplateTree); 59239462Sdim Diags.setShowColors(Opts.ShowColors); 60239462Sdim 61207619Srdivacky // Handle -ferror-limit 62207619Srdivacky if (Opts.ErrorLimit) 63207619Srdivacky Diags.setErrorLimit(Opts.ErrorLimit); 64207619Srdivacky if (Opts.TemplateBacktraceLimit) 65207619Srdivacky Diags.setTemplateBacktraceLimit(Opts.TemplateBacktraceLimit); 66234353Sdim if (Opts.ConstexprBacktraceLimit) 67234353Sdim Diags.setConstexprBacktraceLimit(Opts.ConstexprBacktraceLimit); 68193326Sed 69193326Sed // If -pedantic or -pedantic-errors was specified, then we want to map all 70193326Sed // extension diagnostics onto WARNING or ERROR unless the user has futz'd 71193326Sed // around with them explicitly. 72199482Srdivacky if (Opts.PedanticErrors) 73226633Sdim Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Error); 74199482Srdivacky else if (Opts.Pedantic) 75226633Sdim Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Warn); 76193326Sed else 77226633Sdim Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Ignore); 78198092Srdivacky 79249423Sdim SmallVector<diag::kind, 10> _Diags; 80234353Sdim const IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs = 81234353Sdim Diags.getDiagnosticIDs(); 82234353Sdim // We parse the warning options twice. The first pass sets diagnostic state, 83234353Sdim // while the second pass reports warnings/errors. This has the effect that 84234353Sdim // we follow the more canonical "last option wins" paradigm when there are 85234353Sdim // conflicting options. 86234353Sdim for (unsigned Report = 0, ReportEnd = 2; Report != ReportEnd; ++Report) { 87234353Sdim bool SetDiagnostic = (Report == 0); 88249423Sdim 89249423Sdim // If we've set the diagnostic state and are not reporting diagnostics then 90249423Sdim // we're done. 91249423Sdim if (!SetDiagnostic && !ReportDiags) 92249423Sdim break; 93249423Sdim 94234353Sdim for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) { 95234353Sdim StringRef Opt = Opts.Warnings[i]; 96239462Sdim StringRef OrigOpt = Opts.Warnings[i]; 97198092Srdivacky 98234353Sdim // Treat -Wformat=0 as an alias for -Wno-format. 99234353Sdim if (Opt == "format=0") 100234353Sdim Opt = "no-format"; 101193326Sed 102234353Sdim // Check to see if this warning starts with "no-", if so, this is a 103234353Sdim // negative form of the option. 104234353Sdim bool isPositive = true; 105234353Sdim if (Opt.startswith("no-")) { 106234353Sdim isPositive = false; 107234353Sdim Opt = Opt.substr(3); 108193326Sed } 109198092Srdivacky 110234353Sdim // Figure out how this option affects the warning. If -Wfoo, map the 111234353Sdim // diagnostic to a warning, if -Wno-foo, map it to ignore. 112234353Sdim diag::Mapping Mapping = isPositive ? diag::MAP_WARNING : diag::MAP_IGNORE; 113234353Sdim 114234353Sdim // -Wsystem-headers is a special case, not driven by the option table. It 115234353Sdim // cannot be controlled with -Werror. 116234353Sdim if (Opt == "system-headers") { 117234353Sdim if (SetDiagnostic) 118234353Sdim Diags.setSuppressSystemWarnings(!isPositive); 119193326Sed continue; 120193326Sed } 121234353Sdim 122234353Sdim // -Weverything is a special case as well. It implicitly enables all 123234353Sdim // warnings, including ones not explicitly in a warning group. 124234353Sdim if (Opt == "everything") { 125234353Sdim if (SetDiagnostic) { 126234353Sdim if (isPositive) { 127234353Sdim Diags.setEnableAllWarnings(true); 128234353Sdim } else { 129234353Sdim Diags.setEnableAllWarnings(false); 130234353Sdim Diags.setMappingToAllDiagnostics(diag::MAP_IGNORE); 131234353Sdim } 132234353Sdim } 133234353Sdim continue; 134226633Sdim } 135234353Sdim 136234353Sdim // -Werror/-Wno-error is a special case, not controlled by the option 137234353Sdim // table. It also has the "specifier" form of -Werror=foo and -Werror-foo. 138234353Sdim if (Opt.startswith("error")) { 139234353Sdim StringRef Specifier; 140234353Sdim if (Opt.size() > 5) { // Specifier must be present. 141234353Sdim if ((Opt[5] != '=' && Opt[5] != '-') || Opt.size() == 6) { 142234353Sdim if (Report) 143234353Sdim Diags.Report(diag::warn_unknown_warning_specifier) 144239462Sdim << "-Werror" << ("-W" + OrigOpt.str()); 145234353Sdim continue; 146234353Sdim } 147234353Sdim Specifier = Opt.substr(6); 148234353Sdim } 149234353Sdim 150234353Sdim if (Specifier.empty()) { 151234353Sdim if (SetDiagnostic) 152234353Sdim Diags.setWarningsAsErrors(isPositive); 153201361Srdivacky continue; 154201361Srdivacky } 155234353Sdim 156234353Sdim if (SetDiagnostic) { 157234353Sdim // Set the warning as error flag for this specifier. 158234353Sdim Diags.setDiagnosticGroupWarningAsError(Specifier, isPositive); 159234353Sdim } else if (DiagIDs->getDiagnosticsInGroup(Specifier, _Diags)) { 160234353Sdim EmitUnknownDiagWarning(Diags, "-Werror=", Specifier, isPositive); 161234353Sdim } 162234353Sdim continue; 163201361Srdivacky } 164234353Sdim 165234353Sdim // -Wfatal-errors is yet another special case. 166234353Sdim if (Opt.startswith("fatal-errors")) { 167234353Sdim StringRef Specifier; 168234353Sdim if (Opt.size() != 12) { 169234353Sdim if ((Opt[12] != '=' && Opt[12] != '-') || Opt.size() == 13) { 170234353Sdim if (Report) 171234353Sdim Diags.Report(diag::warn_unknown_warning_specifier) 172239462Sdim << "-Wfatal-errors" << ("-W" + OrigOpt.str()); 173234353Sdim continue; 174234353Sdim } 175234353Sdim Specifier = Opt.substr(13); 176234353Sdim } 177201361Srdivacky 178234353Sdim if (Specifier.empty()) { 179234353Sdim if (SetDiagnostic) 180234353Sdim Diags.setErrorsAsFatal(isPositive); 181234353Sdim continue; 182234353Sdim } 183234353Sdim 184234353Sdim if (SetDiagnostic) { 185234353Sdim // Set the error as fatal flag for this specifier. 186234353Sdim Diags.setDiagnosticGroupErrorAsFatal(Specifier, isPositive); 187234353Sdim } else if (DiagIDs->getDiagnosticsInGroup(Specifier, _Diags)) { 188234353Sdim EmitUnknownDiagWarning(Diags, "-Wfatal-errors=", Specifier, 189234353Sdim isPositive); 190234353Sdim } 191201361Srdivacky continue; 192201361Srdivacky } 193234353Sdim 194234353Sdim if (Report) { 195234353Sdim if (DiagIDs->getDiagnosticsInGroup(Opt, _Diags)) 196239462Sdim EmitUnknownDiagWarning(Diags, isPositive ? "-W" : "-Wno-", Opt, 197239462Sdim isPositive); 198234353Sdim } else { 199234353Sdim Diags.setDiagnosticGroupMapping(Opt, Mapping); 200226633Sdim } 201201361Srdivacky } 202193326Sed } 203193326Sed} 204