Warnings.cpp revision 249423
1193323Sed//===--- Warnings.cpp - C-Language Front-end ------------------------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// Command line warning options handler. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed// 14193323Sed// This file is responsible for handling all warning options. This includes 15193323Sed// a number of -Wfoo options and their variants, which are driven by TableGen- 16193323Sed// generated data, and the special cases -pedantic, -pedantic-errors, -w, 17193323Sed// -Werror and -Wfatal-errors. 18198090Srdivacky// 19249423Sdim// Each warning option controls any number of actual warnings. 20193323Sed// Given a warning option 'foo', the following are valid: 21207618Srdivacky// -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo 22249423Sdim// 23249423Sdim#include "clang/Frontend/Utils.h" 24249423Sdim#include "clang/Basic/Diagnostic.h" 25263508Sdim#include "clang/Basic/DiagnosticOptions.h" 26207618Srdivacky#include "clang/Frontend/FrontendDiagnostic.h" 27198090Srdivacky#include "clang/Lex/LexDiagnostic.h" 28206083Srdivacky#include "clang/Sema/SemaDiagnostic.h" 29198090Srdivacky#include <algorithm> 30193323Sed#include <cstring> 31193323Sed#include <utility> 32207618Srdivackyusing namespace clang; 33207618Srdivacky 34207618Srdivacky// EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning 35207618Srdivacky// opts 36207618Srdivackystatic void EmitUnknownDiagWarning(DiagnosticsEngine &Diags, 37193323Sed StringRef Prefix, StringRef Opt, 38193323Sed bool isPositive) { 39193323Sed StringRef Suggestion = DiagnosticIDs::getNearestWarningOption(Opt); 40198090Srdivacky if (!Suggestion.empty()) 41193323Sed Diags.Report(isPositive? diag::warn_unknown_warning_option_suggest : 42193323Sed diag::warn_unknown_negative_warning_option_suggest) 43193323Sed << (Prefix.str() += Opt) << (Prefix.str() += Suggestion); 44193323Sed else 45193323Sed Diags.Report(isPositive? diag::warn_unknown_warning_option : 46193323Sed diag::warn_unknown_negative_warning_option) 47226633Sdim << (Prefix.str() += Opt); 48226633Sdim} 49193323Sed 50193323Sedvoid clang::ProcessWarningOptions(DiagnosticsEngine &Diags, 51193323Sed const DiagnosticOptions &Opts, 52193323Sed bool ReportDiags) { 53193323Sed Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers 54249423Sdim Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings); 55249423Sdim Diags.setShowOverloads(Opts.getShowOverloads()); 56249423Sdim 57193323Sed Diags.setElideType(Opts.ElideType); 58193323Sed Diags.setPrintTemplateTree(Opts.ShowTemplateTree); 59193323Sed Diags.setWarnOnSpellCheck(Opts.WarnOnSpellCheck); 60193323Sed Diags.setShowColors(Opts.ShowColors); 61193323Sed 62193323Sed // Handle -ferror-limit 63193323Sed if (Opts.ErrorLimit) 64193323Sed Diags.setErrorLimit(Opts.ErrorLimit); 65193323Sed if (Opts.TemplateBacktraceLimit) 66193323Sed Diags.setTemplateBacktraceLimit(Opts.TemplateBacktraceLimit); 67193323Sed if (Opts.ConstexprBacktraceLimit) 68193323Sed Diags.setConstexprBacktraceLimit(Opts.ConstexprBacktraceLimit); 69193323Sed 70193323Sed // If -pedantic or -pedantic-errors was specified, then we want to map all 71202878Srdivacky // extension diagnostics onto WARNING or ERROR unless the user has futz'd 72202878Srdivacky // around with them explicitly. 73202878Srdivacky if (Opts.PedanticErrors) 74193323Sed Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Error); 75193323Sed else if (Opts.Pedantic) 76198090Srdivacky Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Warn); 77193323Sed else 78193323Sed Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Ignore); 79193323Sed 80193323Sed SmallVector<diag::kind, 10> _Diags; 81193323Sed const IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs = 82193323Sed Diags.getDiagnosticIDs(); 83193323Sed // We parse the warning options twice. The first pass sets diagnostic state, 84193323Sed // while the second pass reports warnings/errors. This has the effect that 85198090Srdivacky // we follow the more canonical "last option wins" paradigm when there are 86198090Srdivacky // conflicting options. 87193323Sed for (unsigned Report = 0, ReportEnd = 2; Report != ReportEnd; ++Report) { 88193323Sed bool SetDiagnostic = (Report == 0); 89193323Sed 90193323Sed // If we've set the diagnostic state and are not reporting diagnostics then 91193323Sed // we're done. 92198090Srdivacky if (!SetDiagnostic && !ReportDiags) 93198090Srdivacky break; 94207618Srdivacky 95207618Srdivacky for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) { 96207618Srdivacky StringRef Opt = Opts.Warnings[i]; 97207618Srdivacky StringRef OrigOpt = Opts.Warnings[i]; 98207618Srdivacky 99207618Srdivacky // Treat -Wformat=0 as an alias for -Wno-format. 100207618Srdivacky if (Opt == "format=0") 101198090Srdivacky Opt = "no-format"; 102193323Sed 103193323Sed // Check to see if this warning starts with "no-", if so, this is a 104198090Srdivacky // negative form of the option. 105198090Srdivacky bool isPositive = true; 106198090Srdivacky if (Opt.startswith("no-")) { 107198090Srdivacky isPositive = false; 108206124Srdivacky Opt = Opt.substr(3); 109207618Srdivacky } 110207618Srdivacky 111207618Srdivacky // Figure out how this option affects the warning. If -Wfoo, map the 112198090Srdivacky // diagnostic to a warning, if -Wno-foo, map it to ignore. 113202878Srdivacky diag::Mapping Mapping = isPositive ? diag::MAP_WARNING : diag::MAP_IGNORE; 114202878Srdivacky 115202878Srdivacky // -Wsystem-headers is a special case, not driven by the option table. It 116202878Srdivacky // cannot be controlled with -Werror. 117198090Srdivacky if (Opt == "system-headers") { 118207618Srdivacky if (SetDiagnostic) 119198090Srdivacky Diags.setSuppressSystemWarnings(!isPositive); 120198090Srdivacky continue; 121198090Srdivacky } 122206083Srdivacky 123206083Srdivacky // -Weverything is a special case as well. It implicitly enables all 124206083Srdivacky // warnings, including ones not explicitly in a warning group. 125206083Srdivacky if (Opt == "everything") { 126198090Srdivacky if (SetDiagnostic) { 127198090Srdivacky if (isPositive) { 128198090Srdivacky Diags.setEnableAllWarnings(true); 129198090Srdivacky } else { 130198090Srdivacky Diags.setEnableAllWarnings(false); 131198090Srdivacky Diags.setMappingToAllDiagnostics(diag::MAP_IGNORE); 132198090Srdivacky } 133198090Srdivacky } 134198090Srdivacky continue; 135198090Srdivacky } 136198090Srdivacky 137198090Srdivacky // -Werror/-Wno-error is a special case, not controlled by the option 138202878Srdivacky // table. It also has the "specifier" form of -Werror=foo and -Werror-foo. 139202878Srdivacky if (Opt.startswith("error")) { 140202878Srdivacky StringRef Specifier; 141202878Srdivacky if (Opt.size() > 5) { // Specifier must be present. 142198090Srdivacky if ((Opt[5] != '=' && Opt[5] != '-') || Opt.size() == 6) { 143207618Srdivacky if (Report) 144207618Srdivacky Diags.Report(diag::warn_unknown_warning_specifier) 145207618Srdivacky << "-Werror" << ("-W" + OrigOpt.str()); 146198090Srdivacky continue; 147206083Srdivacky } 148198090Srdivacky Specifier = Opt.substr(6); 149198090Srdivacky } 150198090Srdivacky 151198090Srdivacky if (Specifier.empty()) { 152198090Srdivacky if (SetDiagnostic) 153198090Srdivacky Diags.setWarningsAsErrors(isPositive); 154198090Srdivacky continue; 155201360Srdivacky } 156198090Srdivacky 157198090Srdivacky if (SetDiagnostic) { 158198090Srdivacky // Set the warning as error flag for this specifier. 159198090Srdivacky Diags.setDiagnosticGroupWarningAsError(Specifier, isPositive); 160193323Sed } else if (DiagIDs->getDiagnosticsInGroup(Specifier, _Diags)) { 161193323Sed EmitUnknownDiagWarning(Diags, "-Werror=", Specifier, isPositive); 162198090Srdivacky } 163198090Srdivacky continue; 164198090Srdivacky } 165198090Srdivacky 166198090Srdivacky // -Wfatal-errors is yet another special case. 167198090Srdivacky if (Opt.startswith("fatal-errors")) { 168207618Srdivacky StringRef Specifier; 169207618Srdivacky if (Opt.size() != 12) { 170207618Srdivacky if ((Opt[12] != '=' && Opt[12] != '-') || Opt.size() == 13) { 171207618Srdivacky if (Report) 172207618Srdivacky Diags.Report(diag::warn_unknown_warning_specifier) 173207618Srdivacky << "-Wfatal-errors" << ("-W" + OrigOpt.str()); 174198090Srdivacky continue; 175198090Srdivacky } 176198090Srdivacky Specifier = Opt.substr(13); 177201360Srdivacky } 178198090Srdivacky 179207618Srdivacky if (Specifier.empty()) { 180207618Srdivacky if (SetDiagnostic) 181207618Srdivacky Diags.setErrorsAsFatal(isPositive); 182198090Srdivacky continue; 183198090Srdivacky } 184198090Srdivacky 185207618Srdivacky if (SetDiagnostic) { 186198090Srdivacky // Set the error as fatal flag for this specifier. 187198090Srdivacky Diags.setDiagnosticGroupErrorAsFatal(Specifier, isPositive); 188207618Srdivacky } else if (DiagIDs->getDiagnosticsInGroup(Specifier, _Diags)) { 189207618Srdivacky EmitUnknownDiagWarning(Diags, "-Wfatal-errors=", Specifier, 190207618Srdivacky isPositive); 191207618Srdivacky } 192198090Srdivacky continue; 193198090Srdivacky } 194198090Srdivacky 195198090Srdivacky if (Report) { 196198090Srdivacky if (DiagIDs->getDiagnosticsInGroup(Opt, _Diags)) 197207618Srdivacky EmitUnknownDiagWarning(Diags, isPositive ? "-W" : "-Wno-", Opt, 198207618Srdivacky isPositive); 199207618Srdivacky } else { 200207618Srdivacky Diags.setDiagnosticGroupMapping(Opt, Mapping); 201198090Srdivacky } 202198090Srdivacky } 203198090Srdivacky } 204198090Srdivacky} 205198090Srdivacky