summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clangd/Compiler.cpp3
-rw-r--r--clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp16
-rw-r--r--clang/include/clang/Frontend/CompilerInvocation.h5
-rw-r--r--clang/include/clang/Frontend/Utils.h7
-rw-r--r--clang/lib/Frontend/CreateInvocationFromCommandLine.cpp16
5 files changed, 34 insertions, 13 deletions
diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp
index 22d1fc956bf..7080e20e879 100644
--- a/clang-tools-extra/clangd/Compiler.cpp
+++ b/clang-tools-extra/clangd/Compiler.cpp
@@ -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.
diff --git a/clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp b/clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
index ad013e24a16..7fe57025dc7 100644
--- a/clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
@@ -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
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index 191d2ae9c70..f0280232af0 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -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.
diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h
index 04e786f82ec..0f9b17ee508 100644
--- a/clang/include/clang/Frontend/Utils.h
+++ b/clang/include/clang/Frontend/Utils.h
@@ -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.
diff --git a/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
index d70a3b9a42d..ea7de7a4111 100644
--- a/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -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;
}
OpenPOWER on IntegriCloud