Home | History | Annotate | Download | only in Frontend
      1 //===--- Warnings.cpp - C-Language Front-end ------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // Command line warning options handler.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 //
     14 // This file is responsible for handling all warning options. This includes
     15 // a number of -Wfoo options and their variants, which are driven by TableGen-
     16 // generated data, and the special cases -pedantic, -pedantic-errors, -w,
     17 // -Werror and -Wfatal-errors.
     18 //
     19 // Each warning option controls any number of actual warnings.
     20 // Given a warning option 'foo', the following are valid:
     21 //    -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo
     22 //
     23 #include "clang/Frontend/Utils.h"
     24 #include "clang/Basic/Diagnostic.h"
     25 #include "clang/Sema/SemaDiagnostic.h"
     26 #include "clang/Lex/LexDiagnostic.h"
     27 #include "clang/Frontend/DiagnosticOptions.h"
     28 #include "clang/Frontend/FrontendDiagnostic.h"
     29 #include <cstring>
     30 #include <utility>
     31 #include <algorithm>
     32 using namespace clang;
     33 
     34 void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
     35                                   const DiagnosticOptions &Opts) {
     36   Diags.setSuppressSystemWarnings(true);  // Default to -Wno-system-headers
     37   Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings);
     38   Diags.setShowOverloads(
     39     static_cast<DiagnosticsEngine::OverloadsShown>(Opts.ShowOverloads));
     40 
     41   // Handle -ferror-limit
     42   if (Opts.ErrorLimit)
     43     Diags.setErrorLimit(Opts.ErrorLimit);
     44   if (Opts.TemplateBacktraceLimit)
     45     Diags.setTemplateBacktraceLimit(Opts.TemplateBacktraceLimit);
     46 
     47   // If -pedantic or -pedantic-errors was specified, then we want to map all
     48   // extension diagnostics onto WARNING or ERROR unless the user has futz'd
     49   // around with them explicitly.
     50   if (Opts.PedanticErrors)
     51     Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Error);
     52   else if (Opts.Pedantic)
     53     Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Warn);
     54   else
     55     Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Ignore);
     56 
     57   for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) {
     58     StringRef Opt = Opts.Warnings[i];
     59 
     60     // Check to see if this warning starts with "no-", if so, this is a negative
     61     // form of the option.
     62     bool isPositive = true;
     63     if (Opt.startswith("no-")) {
     64       isPositive = false;
     65       Opt = Opt.substr(3);
     66     }
     67 
     68     // Figure out how this option affects the warning.  If -Wfoo, map the
     69     // diagnostic to a warning, if -Wno-foo, map it to ignore.
     70     diag::Mapping Mapping = isPositive ? diag::MAP_WARNING : diag::MAP_IGNORE;
     71 
     72     // -Wsystem-headers is a special case, not driven by the option table.  It
     73     // cannot be controlled with -Werror.
     74     if (Opt == "system-headers") {
     75       Diags.setSuppressSystemWarnings(!isPositive);
     76       continue;
     77     }
     78 
     79     // -Weverything is a special case as well.  It implicitly enables all
     80     // warnings, including ones not explicitly in a warning group.
     81     if (Opt == "everything") {
     82       Diags.setEnableAllWarnings(true);
     83       continue;
     84     }
     85 
     86     // -Werror/-Wno-error is a special case, not controlled by the option table.
     87     // It also has the "specifier" form of -Werror=foo and -Werror-foo.
     88     if (Opt.startswith("error")) {
     89       StringRef Specifier;
     90       if (Opt.size() > 5) {  // Specifier must be present.
     91         if ((Opt[5] != '=' && Opt[5] != '-') || Opt.size() == 6) {
     92           Diags.Report(diag::warn_unknown_warning_specifier)
     93             << "-Werror" << ("-W" + Opt.str());
     94           continue;
     95         }
     96         Specifier = Opt.substr(6);
     97       }
     98 
     99       if (Specifier.empty()) {
    100         Diags.setWarningsAsErrors(isPositive);
    101         continue;
    102       }
    103 
    104       // Set the warning as error flag for this specifier.
    105       if (Diags.setDiagnosticGroupWarningAsError(Specifier, isPositive)) {
    106         Diags.Report(isPositive ? diag::warn_unknown_warning_option :
    107                      diag::warn_unknown_negative_warning_option)
    108           << ("-W" + Opt.str());
    109       }
    110       continue;
    111     }
    112 
    113     // -Wfatal-errors is yet another special case.
    114     if (Opt.startswith("fatal-errors")) {
    115       StringRef Specifier;
    116       if (Opt.size() != 12) {
    117         if ((Opt[12] != '=' && Opt[12] != '-') || Opt.size() == 13) {
    118           Diags.Report(diag::warn_unknown_warning_specifier)
    119             << "-Wfatal-errors" << ("-W" + Opt.str());
    120           continue;
    121         }
    122         Specifier = Opt.substr(13);
    123       }
    124 
    125       if (Specifier.empty()) {
    126         Diags.setErrorsAsFatal(isPositive);
    127         continue;
    128       }
    129 
    130       // Set the error as fatal flag for this specifier.
    131       if (Diags.setDiagnosticGroupErrorAsFatal(Specifier, isPositive)) {
    132         Diags.Report(isPositive ? diag::warn_unknown_warning_option :
    133                      diag::warn_unknown_negative_warning_option)
    134           << ("-W" + Opt.str());
    135       }
    136       continue;
    137     }
    138 
    139     if (Diags.setDiagnosticGroupMapping(Opt, Mapping)) {
    140       Diags.Report(isPositive ? diag::warn_unknown_warning_option :
    141                    diag::warn_unknown_negative_warning_option)
    142           << ("-W" + Opt.str());
    143     }
    144   }
    145 }
    146