From: Younan Zhang Date: Mon, 28 Aug 2023 06:51:59 +0000 (+0800) Subject: [clang][clangd] Ensure the stack bottom before building AST X-Git-Tag: upstream/17.0.6~137 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5b4513afa40647eab89c5a55ab2d1c893229e873;p=platform%2Fupstream%2Fllvm.git [clang][clangd] Ensure the stack bottom before building AST `clang::runWithSufficientStackSpace` requires the address of the initial stack bottom to prevent potential stack overflows. In addition, add a fallback to ASTFrontendAction in case any client forgets to call it when not through CompilerInstance::ExecuteAction, which is rare. Fixes https://github.com/clangd/clangd/issues/1745. Reviewed By: sammccall Differential Revision: https://reviews.llvm.org/D158967 (cherry picked from commit e257c0a9190637e44e292271103a13d70bec4b03) --- diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index d44d1e2..8b542d0 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -34,6 +34,7 @@ #include "support/MemoryTree.h" #include "support/ThreadsafeFS.h" #include "support/Trace.h" +#include "clang/Basic/Stack.h" #include "clang/Format/Format.h" #include "clang/Lex/Preprocessor.h" #include "clang/Tooling/CompilationDatabase.h" @@ -52,8 +53,8 @@ #include #include #include -#include #include +#include namespace clang { namespace clangd { @@ -112,6 +113,7 @@ struct UpdateIndexCallbacks : public ParsingCallbacks { FIndex(FIndex), // shared_ptr extends lifetime Stdlib(Stdlib)]() mutable { + clang::noteBottomOfStack(); IndexFileIn IF; IF.Symbols = indexStandardLibrary(std::move(CI), Loc, *TFS); if (Stdlib->isBest(LO)) diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp index dd2ce16..324ba1f 100644 --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -63,6 +63,7 @@ #include "support/ThreadCrashReporter.h" #include "support/Threading.h" #include "support/Trace.h" +#include "clang/Basic/Stack.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/FunctionExtras.h" @@ -464,6 +465,10 @@ public: } void run() { + // We mark the current as the stack bottom so that clang running on this + // thread can notice the stack usage and prevent stack overflow with best + // efforts. Same applies to other calls thoughout clangd. + clang::noteBottomOfStack(); while (true) { std::optional Throttle; { @@ -1383,6 +1388,7 @@ void ASTWorker::startTask(llvm::StringRef Name, } void ASTWorker::run() { + clang::noteBottomOfStack(); while (true) { { std::unique_lock Lock(Mutex); @@ -1777,6 +1783,7 @@ void TUScheduler::runWithPreamble(llvm::StringRef Name, PathRef File, Ctx = Context::current().derive(FileBeingProcessed, std::string(File)), Action = std::move(Action), this]() mutable { + clang::noteBottomOfStack(); ThreadCrashReporter ScopedReporter([&Name, &Contents, &Command]() { llvm::errs() << "Signalled during preamble action: " << Name << "\n"; crashDumpCompileCommand(llvm::errs(), Command); diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp index c35de75..7ef9511 100644 --- a/clang-tools-extra/clangd/index/Background.cpp +++ b/clang-tools-extra/clangd/index/Background.cpp @@ -30,6 +30,7 @@ #include "support/Trace.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Stack.h" #include "clang/Frontend/FrontendAction.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" @@ -108,6 +109,7 @@ BackgroundIndex::BackgroundIndex( for (unsigned I = 0; I < Opts.ThreadPoolSize; ++I) { ThreadPool.runAsync("background-worker-" + llvm::Twine(I + 1), [this, Ctx(Context::current().clone())]() mutable { + clang::noteBottomOfStack(); WithContext BGContext(std::move(Ctx)); Queue.work([&] { Rebuilder.idle(); }); }); diff --git a/clang-tools-extra/clangd/test/infinite-instantiation.test b/clang-tools-extra/clangd/test/infinite-instantiation.test new file mode 100644 index 0000000..85a1b65 --- /dev/null +++ b/clang-tools-extra/clangd/test/infinite-instantiation.test @@ -0,0 +1,13 @@ +// RUN: cp %s %t.cpp +// RUN: not clangd -check=%t.cpp 2>&1 | FileCheck -strict-whitespace %s + +// CHECK: [template_recursion_depth_exceeded] + +template +constexpr int f(T... args) { + return f(0, args...); +} + +int main() { + auto i = f(); +} diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index ca5cced..f656a8c 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -29,6 +29,7 @@ #include "support/ThreadCrashReporter.h" #include "support/ThreadsafeFS.h" #include "support/Trace.h" +#include "clang/Basic/Stack.h" #include "clang/Format/Format.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" @@ -710,6 +711,9 @@ enum class ErrorResultCode : int { }; int clangdMain(int argc, char *argv[]) { + // Clang could run on the main thread. e.g., when the flag '-check' or '-sync' + // is enabled. + clang::noteBottomOfStack(); llvm::InitializeAllTargetInfos(); llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); llvm::sys::AddSignalHandler( diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index c6f958a..0bd4b01 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -15,6 +15,7 @@ #include "clang/Basic/FileEntry.h" #include "clang/Basic/LangStandard.h" #include "clang/Basic/Sarif.h" +#include "clang/Basic/Stack.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" @@ -1150,6 +1151,10 @@ void ASTFrontendAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); if (!CI.hasPreprocessor()) return; + // This is a fallback: If the client forgets to invoke this, we mark the + // current stack as the bottom. Though not optimal, this could help prevent + // stack overflow during deep recursion. + clang::noteBottomOfStack(); // FIXME: Move the truncation aspect of this into Sema, we delayed this till // here so the source manager would be initialized.