Skip to content

Commit 72439b6

Browse files
committed
[clangd] Add a flag to turn on recovery-expr.
Reviewers: sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D77142
1 parent 531b3af commit 72439b6

File tree

8 files changed

+48
-1
lines changed

8 files changed

+48
-1
lines changed

clang-tools-extra/clangd/ClangdServer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
134134
: nullptr),
135135
GetClangTidyOptions(Opts.GetClangTidyOptions),
136136
SuggestMissingIncludes(Opts.SuggestMissingIncludes),
137-
TweakFilter(Opts.TweakFilter), WorkspaceRoot(Opts.WorkspaceRoot),
137+
BuildRecoveryAST(Opts.BuildRecoveryAST), TweakFilter(Opts.TweakFilter),
138+
WorkspaceRoot(Opts.WorkspaceRoot),
138139
// Pass a callback into `WorkScheduler` to extract symbols from a newly
139140
// parsed file and rebuild the file index synchronously each time an AST
140141
// is parsed.
@@ -191,6 +192,7 @@ void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents,
191192
Inputs.ForceRebuild = ForceRebuild;
192193
Inputs.Opts = std::move(Opts);
193194
Inputs.Index = Index;
195+
Inputs.Opts.BuildRecoveryAST = BuildRecoveryAST;
194196
bool NewFile = WorkScheduler.update(File, Inputs, WantDiags);
195197
// If we loaded Foo.h, we want to make sure Foo.cpp is indexed.
196198
if (NewFile && BackgroundIdx)

clang-tools-extra/clangd/ClangdServer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ class ClangdServer {
118118
/// enabled.
119119
ClangTidyOptionsBuilder GetClangTidyOptions;
120120

121+
/// If true, turn on the `-frecovery-ast` clang flag.
122+
bool BuildRecoveryAST = false;
123+
121124
/// Clangd's workspace root. Relevant for "workspace" operations not bound
122125
/// to a particular file.
123126
/// FIXME: If not set, should use the current working directory.
@@ -345,6 +348,9 @@ class ClangdServer {
345348
// can be caused by missing includes (e.g. member access in incomplete type).
346349
bool SuggestMissingIncludes = false;
347350

351+
// If true, preserve expressions in AST for broken code.
352+
bool BuildRecoveryAST = false;
353+
348354
std::function<bool(const Tweak &)> TweakFilter;
349355

350356
// GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)

clang-tools-extra/clangd/Compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class IgnoreDiagnostics : public DiagnosticConsumer {
3838
struct ParseOptions {
3939
tidy::ClangTidyOptions ClangTidyOpts;
4040
bool SuggestMissingIncludes = false;
41+
bool BuildRecoveryAST = false;
4142
};
4243

4344
/// Information required to run clang, e.g. to parse AST or do code completion.

clang-tools-extra/clangd/ParsedAST.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ ParsedAST::build(llvm::StringRef Version,
253253
const PrecompiledPreamble *PreamblePCH =
254254
Preamble ? &Preamble->Preamble : nullptr;
255255

256+
// Recovery expression currently only works for C++.
257+
if (CI->getLangOpts()->CPlusPlus)
258+
CI->getLangOpts()->RecoveryAST = Opts.BuildRecoveryAST;
259+
256260
StoreDiags ASTDiags;
257261
std::string Content = std::string(Buffer->getBuffer());
258262
std::string Filename =

clang-tools-extra/clangd/Preamble.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
132132
// to read back. We rely on dynamic index for the comments instead.
133133
CI.getPreprocessorOpts().WriteCommentListToPCH = false;
134134

135+
// Recovery expression currently only works for C++.
136+
if (CI.getLangOpts()->CPlusPlus)
137+
CI.getLangOpts()->RecoveryAST = Inputs.Opts.BuildRecoveryAST;
138+
135139
CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
136140
if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
137141
log("Couldn't set working directory when building the preamble.");

clang-tools-extra/clangd/tool/ClangdMain.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,15 @@ opt<bool> CrossFileRename{
281281
Hidden,
282282
};
283283

284+
opt<bool> RecoveryAST{
285+
"recovery-ast",
286+
cat(Features),
287+
desc("Preserve expressions in AST for broken code (C++ only). Note that "
288+
"this feature is experimental and may lead to crashes"),
289+
init(false),
290+
Hidden,
291+
};
292+
284293
opt<unsigned> WorkerThreadsCount{
285294
"j",
286295
cat(Misc),
@@ -629,6 +638,7 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
629638
}
630639
Opts.StaticIndex = StaticIdx.get();
631640
Opts.AsyncThreadsCount = WorkerThreadsCount;
641+
Opts.BuildRecoveryAST = RecoveryAST;
632642

633643
clangd::CodeCompleteOptions CCOpts;
634644
CCOpts.IncludeIneligibleResults = IncludeIneligibleResults;

clang-tools-extra/clangd/unittests/FindTargetTests.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ TEST_F(TargetDeclTest, Exprs) {
132132
EXPECT_DECLS("CXXOperatorCallExpr", "void operator()(int n)");
133133
}
134134

135+
TEST_F(TargetDeclTest, Recovery) {
136+
Code = R"cpp(
137+
// error-ok: testing behavior on broken code
138+
int f();
139+
int f(int, int);
140+
int x = [[f]](42);
141+
)cpp";
142+
EXPECT_DECLS("UnresolvedLookupExpr", "int f()", "int f(int, int)");
143+
}
144+
135145
TEST_F(TargetDeclTest, UsingDecl) {
136146
Code = R"cpp(
137147
namespace foo {
@@ -685,6 +695,15 @@ TEST_F(FindExplicitReferencesTest, All) {
685695
)cpp",
686696
"0: targets = {x}\n"
687697
"1: targets = {X::a}\n"},
698+
{R"cpp(
699+
// error-ok: testing with broken code
700+
int bar();
701+
int foo() {
702+
return $0^bar() + $1^bar(42);
703+
}
704+
)cpp",
705+
"0: targets = {bar}\n"
706+
"1: targets = {bar}\n"},
688707
// Namespaces and aliases.
689708
{R"cpp(
690709
namespace ns {}

clang-tools-extra/clangd/unittests/TestTU.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ ParseInputs TestTU::inputs() const {
5656
Inputs.Contents = Code;
5757
Inputs.FS = buildTestFS(Files);
5858
Inputs.Opts = ParseOptions();
59+
Inputs.Opts.BuildRecoveryAST = true;
5960
Inputs.Opts.ClangTidyOpts.Checks = ClangTidyChecks;
6061
Inputs.Opts.ClangTidyOpts.WarningsAsErrors = ClangTidyWarningsAsErrors;
6162
Inputs.Index = ExternalIndex;

0 commit comments

Comments
 (0)