[PATCH] D143418: [libclang] Add API to set preferred temp dir path

Igor Kushnir via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 6 09:51:32 PST 2023


vedgy created this revision.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
vedgy requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added projects: clang, clang-tools-extra.

TempPCHFile::create() calls llvm::sys::fs::createTemporaryFile() to
create a file named preamble-*.pch in a system temporary directory. This
commit allows to override the directory where these often many and large
preamble-*.pch files are stored. The added API is named generally to
store other temporary files created by libclang in the same overridden
preferred temporary directory, once such other files are discovered.

A libclang user passes a preferred temporary directory path to
clang_CXIndex_setPreferredTempDirPath(), which stores it in
CIndexer::PreferredTempDirPath. Whenever
clang_parseTranslationUnit_Impl() is called, it passes
CIndexer::PreferredTempDirPath to ASTUnit::LoadFromCommandLine(), which
stores this argument in ASTUnit::PreferredTempDirPath. Whenever
ASTUnit::getMainBufferWithPrecompiledPreamble() is called, it passes
ASTUnit::PreferredTempDirPath to PrecompiledPreamble::Build().
PrecompiledPreamble::Build() forwards the corresponding StoragePath
argument to TempPCHFile::create(). If StoragePath is not empty,
TempPCHFile::create() stores the preamble-*.pch file in the directory at
the specified path rather than in the system temporary directory.

The analysis below proves that this passing around of the
PreferredTempDirPath string is sufficient to guarantee that the libclang
user override is used in TempPCHFile::create(). The analysis ignores API
uses in test code.

TempPCHFile::create() is called only in PrecompiledPreamble::Build().
PrecompiledPreamble::Build() is called only in two places: one in
clangd, which is not used by libclang, and one in
ASTUnit::getMainBufferWithPrecompiledPreamble().
ASTUnit::getMainBufferWithPrecompiledPreamble() is called in 3 places:

1. ASTUnit::LoadFromCompilerInvocation() [analyzed below].
2. ASTUnit::Reparse(), which in turn is called only from

clang_reparseTranslationUnit_Impl(), which in turn is called only from
clang_reparseTranslationUnit(). clang_reparseTranslationUnit() is never
called in LLVM code, but is part of public libclang API. This function's
documentation requires its translation unit argument to have been built
with clang_createTranslationUnitFromSourceFile().
clang_createTranslationUnitFromSourceFile() delegates its work to
clang_parseTranslationUnit(), which delegates to
clang_parseTranslationUnit2(), which delegates to
clang_parseTranslationUnit2FullArgv(), which delegates to
clang_parseTranslationUnit_Impl(), which passes
CIndexer::PreferredTempDirPath to the ASTUnit it creates.

3. ASTUnit::CodeComplete() passes AllowRebuild = false to

ASTUnit::getMainBufferWithPrecompiledPreamble(), which makes it return
nullptr before calling PrecompiledPreamble::Build().

Both ASTUnit::LoadFromCompilerInvocation() overloads (one of which
delegates its work to another) call
ASTUnit::getMainBufferWithPrecompiledPreamble() only if their argument
PrecompilePreambleAfterNParses > 0. LoadFromCompilerInvocation() is
called in:

1. ASTBuilderAction::runInvocation() keeps the default parameter value

of PrecompilePreambleAfterNParses = 0, meaning that the preamble file is
never created from here.

2. ASTUnit::LoadFromCommandLine().

ASTUnit::LoadFromCommandLine() is called in two places:

1. CrossTranslationUnitContext::ASTLoader::loadFromSource() keeps the

default parameter value of PrecompilePreambleAfterNParses = 0, meaning
that the preamble file is never created from here.

2. clang_parseTranslationUnit_Impl(), which passes

CIndexer::PreferredTempDirPath to the ASTUnit it creates.

TempPCHFile::create() uses PreferredTempDirPath in the same way as
LibclangInvocationReporter() uses InvocationEmissionPath. The
documentation for clang_CXIndex_setInvocationEmissionPathOption() does
not specify ownership, encoding, relative vs absolute path or separator
requirements. So the new function's documentation doesn't either.

The added function clang_CXIndex_setPreferredTempDirPath() works as
expected in KDevelop:
https://invent.kde.org/kdevelop/kdevelop/-/merge_requests/283

Fixes: https://github.com/llvm/llvm-project/issues/51847

Depends on D143415 <https://reviews.llvm.org/D143415>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D143418

Files:
  clang-tools-extra/clangd/Preamble.cpp
  clang/docs/ReleaseNotes.rst
  clang/include/clang-c/Index.h
  clang/include/clang/Frontend/ASTUnit.h
  clang/include/clang/Frontend/PrecompiledPreamble.h
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Frontend/PrecompiledPreamble.cpp
  clang/tools/libclang/CIndex.cpp
  clang/tools/libclang/CIndexer.h
  clang/tools/libclang/libclang.map
  clang/unittests/Frontend/ASTUnitTest.cpp
  clang/unittests/libclang/LibclangTest.cpp
  clang/unittests/libclang/TestUtils.h

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D143418.495190.patch
Type: text/x-patch
Size: 18601 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230206/a4978ff4/attachment-0001.bin>


More information about the cfe-commits mailing list