[Driver] Add an option for createInvocationFromCommandLine to recover on errors
Summary: Previously, it would always return nullptr on any error. This change adds a parameter, controlling whether the function should attempt to return a non-null result even if unknown arguments (or other errors were encountered). The new behavior is only used in clangd. Considered an alternative of changing the return value instead of adding a new parameter, but that would require updating all callsites. Settled with the parameter to minimize the code changes. Reviewers: gribozavr Reviewed By: gribozavr Subscribers: nridge, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66731 llvm-svn: 370033
This commit is contained in:
parent
7a2e21d9f4
commit
999e4c4793
|
@ -59,7 +59,8 @@ buildCompilerInvocation(const ParseInputs &Inputs) {
|
|||
CompilerInstance::createDiagnostics(new DiagnosticOptions,
|
||||
&IgnoreDiagnostics, false);
|
||||
std::unique_ptr<CompilerInvocation> CI = createInvocationFromCommandLine(
|
||||
ArgStrs, CommandLineDiagsEngine, Inputs.FS);
|
||||
ArgStrs, CommandLineDiagsEngine, Inputs.FS,
|
||||
/*ShouldRecoverOnErrors=*/true);
|
||||
if (!CI)
|
||||
return nullptr;
|
||||
// createInvocationFromCommandLine sets DisableFree.
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
#include "AST.h"
|
||||
#include "Annotations.h"
|
||||
#include "ClangdUnit.h"
|
||||
#include "Compiler.h"
|
||||
#include "SourceCode.h"
|
||||
#include "TestFS.h"
|
||||
#include "TestTU.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/Basic/TokenKinds.h"
|
||||
|
@ -244,6 +246,20 @@ TEST(ClangdUnitTest, NoCrashOnTokensWithTidyCheck) {
|
|||
EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "}");
|
||||
}
|
||||
|
||||
TEST(ClangdUnitTest, CanBuildInvocationWithUnknownArgs) {
|
||||
// Unknown flags should not prevent a build of compiler invocation.
|
||||
ParseInputs Inputs;
|
||||
Inputs.FS = buildTestFS({{testPath("foo.cpp"), "void test() {}"}});
|
||||
Inputs.CompileCommand.CommandLine = {"clang", "-fsome-unknown-flag",
|
||||
testPath("foo.cpp")};
|
||||
EXPECT_NE(buildCompilerInvocation(Inputs), nullptr);
|
||||
|
||||
// Unknown forwarded to -cc1 should not a failure either.
|
||||
Inputs.CompileCommand.CommandLine = {
|
||||
"clang", "-Xclang", "-fsome-unknown-flag", testPath("foo.cpp")};
|
||||
EXPECT_NE(buildCompilerInvocation(Inputs), nullptr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
|
|
@ -147,6 +147,11 @@ public:
|
|||
/// Create a compiler invocation from a list of input options.
|
||||
/// \returns true on success.
|
||||
///
|
||||
/// \returns false if an error was encountered while parsing the arguments
|
||||
/// and attempts to recover and continue parsing the rest of the arguments.
|
||||
/// The recovery is best-effort and only guarantees that \p Res will end up in
|
||||
/// one of the vaild-to-access (albeit arbitrary) states.
|
||||
///
|
||||
/// \param [out] Res - The resulting invocation.
|
||||
/// \param ArgBegin - The first element in the argument vector.
|
||||
/// \param ArgEnd - The last element in the argument vector.
|
||||
|
|
|
@ -213,13 +213,18 @@ createChainedIncludesSource(CompilerInstance &CI,
|
|||
/// createInvocationFromCommandLine - Construct a compiler invocation object for
|
||||
/// a command line argument vector.
|
||||
///
|
||||
/// \param ShouldRecoverOnErrors - whether we should attempt to return a
|
||||
/// non-null (and possibly incorrect) CompilerInvocation if any errors were
|
||||
/// encountered. When this flag is false, always return null on errors.
|
||||
///
|
||||
/// \return A CompilerInvocation, or 0 if none was built for the given
|
||||
/// argument vector.
|
||||
std::unique_ptr<CompilerInvocation> createInvocationFromCommandLine(
|
||||
ArrayRef<const char *> Args,
|
||||
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
|
||||
IntrusiveRefCntPtr<DiagnosticsEngine>(),
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr,
|
||||
bool ShouldRecoverOnErrors = false);
|
||||
|
||||
/// 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.
|
||||
|
|
|
@ -24,14 +24,9 @@
|
|||
using namespace clang;
|
||||
using namespace llvm::opt;
|
||||
|
||||
/// createInvocationFromCommandLine - Construct a compiler invocation object for
|
||||
/// a command line argument vector.
|
||||
///
|
||||
/// \return A CompilerInvocation, or 0 if none was built for the given
|
||||
/// argument vector.
|
||||
std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine(
|
||||
ArrayRef<const char *> ArgList, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool ShouldRecoverOnErorrs) {
|
||||
if (!Diags.get()) {
|
||||
// No diagnostics engine was provided, so create our own diagnostics object
|
||||
// with the default options.
|
||||
|
@ -95,11 +90,10 @@ std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine(
|
|||
|
||||
const ArgStringList &CCArgs = Cmd.getArguments();
|
||||
auto CI = std::make_unique<CompilerInvocation>();
|
||||
if (!CompilerInvocation::CreateFromArgs(*CI,
|
||||
const_cast<const char **>(CCArgs.data()),
|
||||
const_cast<const char **>(CCArgs.data()) +
|
||||
CCArgs.size(),
|
||||
*Diags))
|
||||
if (!CompilerInvocation::CreateFromArgs(
|
||||
*CI, const_cast<const char **>(CCArgs.data()),
|
||||
const_cast<const char **>(CCArgs.data()) + CCArgs.size(), *Diags) &&
|
||||
!ShouldRecoverOnErorrs)
|
||||
return nullptr;
|
||||
return CI;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue