зеркало из https://github.com/microsoft/clang-1.git
[driver] Parse diagnostic args in the driver.
Previously, only diagnostics thrown by the cc1 process were actually honoring the diagnostic options given on the command line, like -Werror. Reuse the existing code in Frontend currently used for cc1, adjusting it to not interpret -Wl, linker flags as warnings. Also fix a faulty test exposed by this change. It wasn't actually testing anything, and was giving this warning: clang-3: warning: argument unused during compilation: '-verify' Which -Werror didn't turn into an error because it was output by the driver, not the cc1 process, and diagnostic options weren't parsed by the driver. And you couldn't see the warning when running the test suite. Fixes PR12181. Patch by Dylan Noblesmith <nobled@dreamwidth.org>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152660 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
b990d039c7
Коммит
2dec85b218
|
@ -204,10 +204,18 @@ namespace driver {
|
||||||
StringRef getLastArgValue(OptSpecifier Id,
|
StringRef getLastArgValue(OptSpecifier Id,
|
||||||
StringRef Default = "") const;
|
StringRef Default = "") const;
|
||||||
|
|
||||||
|
/// getLastArgValue - Return the value of the last argument as an integer,
|
||||||
|
/// or a default. If Diags is non-null, emits an error if the argument
|
||||||
|
/// is given, but non-integral.
|
||||||
|
int getLastArgIntValue(OptSpecifier Id, int Default,
|
||||||
|
DiagnosticsEngine *Diags = 0) const;
|
||||||
|
|
||||||
/// getLastArgValue - Return the value of the last argument as an integer,
|
/// getLastArgValue - Return the value of the last argument as an integer,
|
||||||
/// or a default. Emits an error if the argument is given, but non-integral.
|
/// or a default. Emits an error if the argument is given, but non-integral.
|
||||||
int getLastArgIntValue(OptSpecifier Id, int Default,
|
int getLastArgIntValue(OptSpecifier Id, int Default,
|
||||||
DiagnosticsEngine &Diags) const;
|
DiagnosticsEngine &Diags) const {
|
||||||
|
return getLastArgIntValue(Id, Default, &Diags);
|
||||||
|
}
|
||||||
|
|
||||||
/// getAllArgValues - Get the values of all instances of the given argument
|
/// getAllArgValues - Get the values of all instances of the given argument
|
||||||
/// as strings.
|
/// as strings.
|
||||||
|
|
|
@ -33,6 +33,17 @@ namespace clang {
|
||||||
|
|
||||||
class CompilerInvocation;
|
class CompilerInvocation;
|
||||||
class DiagnosticsEngine;
|
class DiagnosticsEngine;
|
||||||
|
|
||||||
|
namespace driver {
|
||||||
|
class ArgList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CompilerInvocation - Fill out Opts based on the options given in Args.
|
||||||
|
/// Args must have been created from the OptTable returned by
|
||||||
|
/// createCC1OptTable(). When errors are encountered, return false and,
|
||||||
|
/// if Diags is non-null, report the error(s).
|
||||||
|
bool ParseDiagnosticArgs(DiagnosticOptions &Opts, driver::ArgList &Args,
|
||||||
|
DiagnosticsEngine *Diags = 0);
|
||||||
|
|
||||||
class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
|
class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -154,13 +154,15 @@ StringRef ArgList::getLastArgValue(OptSpecifier Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
int ArgList::getLastArgIntValue(OptSpecifier Id, int Default,
|
int ArgList::getLastArgIntValue(OptSpecifier Id, int Default,
|
||||||
clang::DiagnosticsEngine &Diags) const {
|
clang::DiagnosticsEngine *Diags) const {
|
||||||
int Res = Default;
|
int Res = Default;
|
||||||
|
|
||||||
if (Arg *A = getLastArg(Id)) {
|
if (Arg *A = getLastArg(Id)) {
|
||||||
if (StringRef(A->getValue(*this)).getAsInteger(10, Res))
|
if (StringRef(A->getValue(*this)).getAsInteger(10, Res)) {
|
||||||
Diags.Report(diag::err_drv_invalid_int_value)
|
if (Diags)
|
||||||
<< A->getAsString(*this) << A->getValue(*this);
|
Diags->Report(diag::err_drv_invalid_int_value)
|
||||||
|
<< A->getAsString(*this) << A->getValue(*this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Res;
|
return Res;
|
||||||
|
|
|
@ -1277,8 +1277,8 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
|
||||||
Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
|
Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
||||||
DiagnosticsEngine &Diags) {
|
DiagnosticsEngine *Diags) {
|
||||||
using namespace cc1options;
|
using namespace cc1options;
|
||||||
bool Success = true;
|
bool Success = true;
|
||||||
|
|
||||||
|
@ -1312,10 +1312,11 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
||||||
else if (ShowOverloads == "all")
|
else if (ShowOverloads == "all")
|
||||||
Opts.ShowOverloads = DiagnosticsEngine::Ovl_All;
|
Opts.ShowOverloads = DiagnosticsEngine::Ovl_All;
|
||||||
else {
|
else {
|
||||||
Diags.Report(diag::err_drv_invalid_value)
|
Success = false;
|
||||||
|
if (Diags)
|
||||||
|
Diags->Report(diag::err_drv_invalid_value)
|
||||||
<< Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
|
<< Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
|
||||||
<< ShowOverloads;
|
<< ShowOverloads;
|
||||||
Success = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef ShowCategory =
|
StringRef ShowCategory =
|
||||||
|
@ -1327,10 +1328,11 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
||||||
else if (ShowCategory == "name")
|
else if (ShowCategory == "name")
|
||||||
Opts.ShowCategories = 2;
|
Opts.ShowCategories = 2;
|
||||||
else {
|
else {
|
||||||
Diags.Report(diag::err_drv_invalid_value)
|
Success = false;
|
||||||
|
if (Diags)
|
||||||
|
Diags->Report(diag::err_drv_invalid_value)
|
||||||
<< Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
|
<< Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
|
||||||
<< ShowCategory;
|
<< ShowCategory;
|
||||||
Success = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef Format =
|
StringRef Format =
|
||||||
|
@ -1342,10 +1344,11 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
||||||
else if (Format == "vi")
|
else if (Format == "vi")
|
||||||
Opts.Format = DiagnosticOptions::Vi;
|
Opts.Format = DiagnosticOptions::Vi;
|
||||||
else {
|
else {
|
||||||
Diags.Report(diag::err_drv_invalid_value)
|
Success = false;
|
||||||
|
if (Diags)
|
||||||
|
Diags->Report(diag::err_drv_invalid_value)
|
||||||
<< Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args)
|
<< Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args)
|
||||||
<< Format;
|
<< Format;
|
||||||
Success = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
|
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
|
||||||
|
@ -1366,13 +1369,23 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
||||||
Opts.TabStop = Args.getLastArgIntValue(OPT_ftabstop,
|
Opts.TabStop = Args.getLastArgIntValue(OPT_ftabstop,
|
||||||
DiagnosticOptions::DefaultTabStop, Diags);
|
DiagnosticOptions::DefaultTabStop, Diags);
|
||||||
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
|
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
|
||||||
Diags.Report(diag::warn_ignoring_ftabstop_value)
|
|
||||||
<< Opts.TabStop << DiagnosticOptions::DefaultTabStop;
|
|
||||||
Opts.TabStop = DiagnosticOptions::DefaultTabStop;
|
Opts.TabStop = DiagnosticOptions::DefaultTabStop;
|
||||||
|
if (Diags)
|
||||||
|
Diags->Report(diag::warn_ignoring_ftabstop_value)
|
||||||
|
<< Opts.TabStop << DiagnosticOptions::DefaultTabStop;
|
||||||
}
|
}
|
||||||
Opts.MessageLength = Args.getLastArgIntValue(OPT_fmessage_length, 0, Diags);
|
Opts.MessageLength = Args.getLastArgIntValue(OPT_fmessage_length, 0, Diags);
|
||||||
Opts.DumpBuildInformation = Args.getLastArgValue(OPT_dump_build_information);
|
Opts.DumpBuildInformation = Args.getLastArgValue(OPT_dump_build_information);
|
||||||
Opts.Warnings = Args.getAllArgValues(OPT_W);
|
|
||||||
|
for (arg_iterator it = Args.filtered_begin(OPT_W),
|
||||||
|
ie = Args.filtered_end(); it != ie; ++it) {
|
||||||
|
StringRef V = (*it)->getValue(Args);
|
||||||
|
// "-Wl," and such are not warnings options.
|
||||||
|
if (V.startswith("l,") || V.startswith("a,") || V.startswith("p,"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Opts.Warnings.push_back(V);
|
||||||
|
}
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
@ -2174,7 +2187,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
|
||||||
Success = ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags) && Success;
|
Success = ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags) && Success;
|
||||||
Success = ParseMigratorArgs(Res.getMigratorOpts(), *Args) && Success;
|
Success = ParseMigratorArgs(Res.getMigratorOpts(), *Args) && Success;
|
||||||
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
|
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
|
||||||
Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags)
|
Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, &Diags)
|
||||||
&& Success;
|
&& Success;
|
||||||
ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
|
ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
|
||||||
// FIXME: We shouldn't have to pass the DashX option around here
|
// FIXME: We shouldn't have to pass the DashX option around here
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Parse diagnostic arguments in the driver
|
||||||
|
// PR12181
|
||||||
|
|
||||||
|
// RUN: !%clang -target x86_64-apple-darwin10 \
|
||||||
|
// RUN: -fsyntax-only -fzyzzybalubah \
|
||||||
|
// RUN: -Werror=unused-command-line-argument %s
|
||||||
|
|
||||||
|
// RUN: !%clang -target x86_64-apple-darwin10 \
|
||||||
|
// RUN: -fsyntax-only -fzyzzybalubah -Werror %s
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang -Werror -fobjc-arc -fsyntax-only -fno-objc-arc -verify %s
|
// RUN: %clang -Werror -fobjc-arc -fsyntax-only -fno-objc-arc -Xclang -verify %s
|
||||||
// rdar://8949617
|
// rdar://8949617
|
||||||
|
|
||||||
void * FOO() {
|
void * FOO() {
|
||||||
|
|
|
@ -12,11 +12,16 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "clang/Driver/ArgList.h"
|
||||||
|
#include "clang/Driver/CC1Options.h"
|
||||||
#include "clang/Driver/Compilation.h"
|
#include "clang/Driver/Compilation.h"
|
||||||
#include "clang/Driver/Driver.h"
|
#include "clang/Driver/Driver.h"
|
||||||
#include "clang/Driver/Option.h"
|
#include "clang/Driver/Option.h"
|
||||||
|
#include "clang/Driver/OptTable.h"
|
||||||
|
#include "clang/Frontend/CompilerInvocation.h"
|
||||||
#include "clang/Frontend/DiagnosticOptions.h"
|
#include "clang/Frontend/DiagnosticOptions.h"
|
||||||
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
||||||
|
#include "clang/Frontend/Utils.h"
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
|
@ -370,11 +375,27 @@ int main(int argc_, const char **argv_) {
|
||||||
|
|
||||||
llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes);
|
llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes);
|
||||||
|
|
||||||
|
DiagnosticOptions DiagOpts;
|
||||||
|
{
|
||||||
|
// Note that ParseDiagnosticArgs() uses the cc1 option table.
|
||||||
|
OwningPtr<OptTable> CC1Opts(createCC1OptTable());
|
||||||
|
unsigned MissingArgIndex, MissingArgCount;
|
||||||
|
OwningPtr<InputArgList> Args(CC1Opts->ParseArgs(argv.begin()+1, argv.end(),
|
||||||
|
MissingArgIndex, MissingArgCount));
|
||||||
|
// We ignore MissingArgCount and the return value of ParseDiagnosticArgs.
|
||||||
|
// Any errors that would be diagnosed here will also be diagnosed later,
|
||||||
|
// when the DiagnosticsEngine actually exists.
|
||||||
|
(void) ParseDiagnosticArgs(DiagOpts, *Args);
|
||||||
|
}
|
||||||
|
// Now we can create the DiagnosticsEngine with a properly-filled-out
|
||||||
|
// DiagnosticOptions instance.
|
||||||
TextDiagnosticPrinter *DiagClient
|
TextDiagnosticPrinter *DiagClient
|
||||||
= new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
|
= new TextDiagnosticPrinter(llvm::errs(), DiagOpts);
|
||||||
DiagClient->setPrefix(llvm::sys::path::stem(Path.str()));
|
DiagClient->setPrefix(llvm::sys::path::stem(Path.str()));
|
||||||
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
|
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
|
||||||
|
|
||||||
DiagnosticsEngine Diags(DiagID, DiagClient);
|
DiagnosticsEngine Diags(DiagID, DiagClient);
|
||||||
|
ProcessWarningOptions(Diags, DiagOpts);
|
||||||
|
|
||||||
#ifdef CLANG_IS_PRODUCTION
|
#ifdef CLANG_IS_PRODUCTION
|
||||||
const bool IsProduction = true;
|
const bool IsProduction = true;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче