/// Whether we're compiling for diagnostic purposes.
bool ForDiagnostics;
+ /// Whether an error during the parsing of the input args.
+ bool ContainsError;
+
public:
Compilation(const Driver &D, const ToolChain &DefaultToolChain,
llvm::opt::InputArgList *Args,
- llvm::opt::DerivedArgList *TranslatedArgs);
+ llvm::opt::DerivedArgList *TranslatedArgs, bool ContainsError);
~Compilation();
const Driver &getDriver() const { return TheDriver; }
/// Return true if we're compiling for diagnostics.
bool isForDiagnostics() const { return ForDiagnostics; }
+ /// Return whether an error during the parsing of the input args.
+ bool containsError() const { return ContainsError; }
+
/// Redirect - Redirect output of this compilation. Can only be done once.
///
/// \param Redirects - array of pointers to paths. The array
using namespace llvm::opt;
Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
- InputArgList *_Args, DerivedArgList *_TranslatedArgs)
+ InputArgList *_Args, DerivedArgList *_TranslatedArgs,
+ bool ContainsError)
: TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u),
Args(_Args), TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
- ForDiagnostics(false) {
+ ForDiagnostics(false), ContainsError(ContainsError) {
// The offloading host toolchain is the default tool chain.
OrderedOffloadingToolchains.insert(
std::make_pair(Action::OFK_Host, &DefaultToolChain));
Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
}
-InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
+InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
+ bool &ContainsError) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
+ ContainsError = false;
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
IncludedFlagsBitmask, ExcludedFlagsBitmask);
// Check for missing argument error.
- if (MissingArgCount)
- Diag(clang::diag::err_drv_missing_argument)
+ if (MissingArgCount) {
+ Diag(diag::err_drv_missing_argument)
<< Args.getArgString(MissingArgIndex) << MissingArgCount;
+ ContainsError |=
+ Diags.getDiagnosticLevel(diag::err_drv_missing_argument,
+ SourceLocation()) > DiagnosticsEngine::Warning;
+ }
// Check for unsupported options.
for (const Arg *A : Args) {
if (A->getOption().hasFlag(options::Unsupported)) {
- Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(Args);
+ Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
+ ContainsError |= Diags.getDiagnosticLevel(diag::err_drv_unsupported_opt,
+ SourceLocation()) >
+ DiagnosticsEngine::Warning;
continue;
}
// Warn about -mcpu= without an argument.
if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) {
- Diag(clang::diag::warn_drv_empty_joined_argument) << A->getAsString(Args);
+ Diag(diag::warn_drv_empty_joined_argument) << A->getAsString(Args);
+ ContainsError |= Diags.getDiagnosticLevel(
+ diag::warn_drv_empty_joined_argument,
+ SourceLocation()) > DiagnosticsEngine::Warning;
}
}
- for (const Arg *A : Args.filtered(options::OPT_UNKNOWN))
- Diags.Report(IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl :
- diag::err_drv_unknown_argument)
- << A->getAsString(Args);
+ for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) {
+ auto ID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl
+ : diag::err_drv_unknown_argument;
+
+ Diags.Report(ID) << A->getAsString(Args);
+ ContainsError |= Diags.getDiagnosticLevel(ID, SourceLocation()) >
+ DiagnosticsEngine::Warning;
+ }
return Args;
}
// FIXME: This stuff needs to go into the Compilation, not the driver.
bool CCCPrintPhases;
- InputArgList Args = ParseArgStrings(ArgList.slice(1));
- if (Diags.hasErrorOccurred())
- return nullptr;
+ bool ContainsError;
+ InputArgList Args = ParseArgStrings(ArgList.slice(1), ContainsError);
// Silence driver warnings if requested
Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w));
*UArgs, computeTargetTriple(*this, DefaultTargetTriple, *UArgs));
// The compilation takes ownership of Args.
- Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs);
+ Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs,
+ ContainsError);
if (!HandleImmediateArgs(*C))
return C;
EXPECT_TRUE(CXXDriver.CCCIsCXX());
EXPECT_TRUE(CLDriver.IsCLMode());
}
+TEST(ToolChainTest, InvalidArgument) {
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ struct TestDiagnosticConsumer : public DiagnosticConsumer {};
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
+ Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags);
+ std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
+ {"-fsyntax-only", "-fan-unknown-option", "foo.cpp"}));
+ EXPECT_TRUE(C);
+ EXPECT_TRUE(C->containsError());
+}
} // end anonymous namespace.