Compare commits

...

6 Commits

Author SHA1 Message Date
rherilier
779cd86a06
Merge 84b3c69ff5 into d31cc9f076 2025-12-02 12:33:26 +08:00
Fangrui Song
d31cc9f076 Adapt llvm 22 changes
Type::Elaborated is removed by llvmorg-22-init-3166-g91cdd35008e9

llvm::sys::fs and clang functions are changed due to
https://discourse.llvm.org/t/rfc-file-system-sandboxing-in-clang-llvm/88791
2025-11-29 21:53:40 -08:00
zhscn
a7068f13ec indexer: Resolve the type alias correctly (#988)
The struct derived from an alias is missing from type hierarchy before this fix:
```cpp
struct Base {};
struct Derived : Base {};
using BaseAlias = Base;
struct DerivedAlias : BaseAlias {};
```
```
Derive from
Base
└╸Derived
```
The expected output is:
```
Derive from
Base
├╸Derived
└╸DerivedAlias
```
2025-11-15 14:27:19 -08:00
Fangrui Song
344e2e6557 Add clang.prependArgs option
To specify arguments that are inserted immediately after the compiler
driver name. For example, initialization options
`{"clang":{"prependArgs":["--gcc-install-dir=/usr/lib/gcc/x86_64-linux-gnu/13"]}}`
transforms `clang -c a.cc` into `clang --gcc-install-dir=/usr/lib/gcc/x86_64-linux-gnu/13 -c a.cc`.
This allows users to provide default arguments that can be overridden as
needed.
2025-08-15 12:00:00 -07:00
Fangrui Song
791f6ba974 indexer: Support Decl::Concept
Fix indexer.cc:802 "Unhandled 72" when compiling `#include <chrono>`
functions with -std=c++20.
2025-11-15 14:03:07 -08:00
Rémi Hérilier
84b3c69ff5 cmake: Make sure to get the resource directory from the right clang compiler
The resource directory was always retrieved from the system's default clang
compiler instead of the targeted one.
2024-12-06 17:08:30 +01:00
7 changed files with 372 additions and 10 deletions

View File

@ -132,11 +132,30 @@ endif()
# Find Clang resource directory with Clang executable.
if(NOT CLANG_RESOURCE_DIR)
find_program(CLANG_EXECUTABLE clang)
find_program(CLANG_EXECUTABLE clang-${Clang_VERSION_MAJOR} NAMES clang)
if(NOT CLANG_EXECUTABLE)
message(FATAL_ERROR "clang executable not found.")
endif()
execute_process(
COMMAND ${CLANG_EXECUTABLE} -dumpversion
RESULT_VARIABLE CLANG_DUMP_VERSION_RESULT
OUTPUT_VARIABLE CLANG_DUMP_VERSION
ERROR_VARIABLE CLANG_DUMP_VERSION_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(CLANG_DUMP_VERSION_RESULT)
message(FATAL_ERROR "Error retrieving Clang executable version. \
Output:\n${CLANG_DUMP_VERSION_ERROR}")
endif()
if (NOT ${CLANG_DUMP_VERSION} STREQUAL ${Clang_VERSION})
message(FATAL_ERROR "Clang libraries and executable versions differs:\n\
librairies have version ${Clang_VERSION} and executable has version \
${CLANG_DUMP_VERSION}.")
endif()
execute_process(
COMMAND ${CLANG_EXECUTABLE} -print-resource-dir
RESULT_VARIABLE CLANG_FIND_RESOURCE_DIR_RESULT

View File

@ -0,0 +1,307 @@
template <class T> struct type_trait {
const static bool value = false;
};
template <> struct type_trait<int> {
const static bool value = true;
};
template <class T>
concept Con1 = type_trait<T>::value;
constexpr int sizeFunc() { return 4; }
template <class T>
concept ConWithLogicalAnd = Con1<T> && sizeof(T) > sizeFunc();
namespace ns {
template <class T>
concept ConInNamespace = sizeof(T) > 4;
}
template <class T1, class T2>
concept ConTwoTemplateParams = ns::ConInNamespace<T1> && ConWithLogicalAnd<T2>;
/*
OUTPUT:
{
"includes": [],
"skipped_ranges": [],
"usr2func": [{
"usr": 3226866773869731400,
"detailed_name": "constexpr int sizeFunc()",
"qual_name_offset": 14,
"short_name": "sizeFunc",
"spell": "13:15-13:23|13:1-13:39|2|-1",
"bases": [],
"vars": [],
"callees": [],
"kind": 12,
"parent_kind": 1,
"storage": 0,
"declarations": [],
"derived": [],
"uses": ["16:52-16:60|36|-1"]
}],
"usr2type": [{
"usr": 436,
"detailed_name": "",
"qual_name_offset": 0,
"short_name": "",
"bases": [],
"funcs": [],
"types": [],
"vars": [],
"alias_of": 0,
"kind": 0,
"parent_kind": 0,
"declarations": [],
"derived": [],
"instances": [3643386974125063532, 4683419091429829178],
"uses": []
}, {
"usr": 452,
"detailed_name": "",
"qual_name_offset": 0,
"short_name": "",
"bases": [],
"funcs": [],
"types": [],
"vars": [],
"alias_of": 0,
"kind": 0,
"parent_kind": 0,
"declarations": [],
"derived": [],
"instances": [15611304989063975809, 15197037962155352994, 7075924720131397743, 8419381068906673567],
"uses": []
}, {
"usr": 368613743269466510,
"detailed_name": "T",
"qual_name_offset": 0,
"short_name": "",
"bases": [],
"funcs": [],
"types": [],
"vars": [],
"alias_of": 0,
"kind": 26,
"parent_kind": 0,
"declarations": ["19:17-19:18|19:11-19:18|1025|-1"],
"derived": [],
"instances": [],
"uses": ["20:33-20:34|4|-1"]
}, {
"usr": 1341599025369786548,
"detailed_name": "T1",
"qual_name_offset": 0,
"short_name": "",
"bases": [],
"funcs": [],
"types": [],
"vars": [],
"alias_of": 0,
"kind": 26,
"parent_kind": 0,
"declarations": ["23:17-23:19|23:11-23:19|1|-1"],
"derived": [],
"instances": [],
"uses": ["24:51-24:53|4|-1"]
}, {
"usr": 1789177110200181456,
"detailed_name": "T",
"qual_name_offset": 0,
"short_name": "",
"bases": [],
"funcs": [],
"types": [],
"vars": [],
"alias_of": 0,
"kind": 26,
"parent_kind": 0,
"declarations": ["15:17-15:18|15:11-15:18|1|-1"],
"derived": [],
"instances": [],
"uses": ["16:34-16:35|4|-1", "16:47-16:48|4|-1"]
}, {
"usr": 4001289545226345448,
"detailed_name": "struct type_trait {}",
"qual_name_offset": 7,
"short_name": "type_trait",
"spell": "2:27-2:37|2:20-4:2|2|-1",
"bases": [],
"funcs": [],
"types": [13813325012676356715],
"vars": [],
"alias_of": 0,
"kind": 23,
"parent_kind": 1,
"declarations": [],
"derived": [10139416838611429657],
"instances": [],
"uses": ["11:16-11:26|4|-1"]
}, {
"usr": 8987540007709901036,
"detailed_name": "T",
"qual_name_offset": 0,
"short_name": "",
"bases": [],
"funcs": [],
"types": [],
"vars": [],
"alias_of": 0,
"kind": 26,
"parent_kind": 0,
"declarations": ["10:17-10:18|10:11-10:18|1|-1"],
"derived": [],
"instances": [],
"uses": ["11:27-11:28|4|-1"]
}, {
"usr": 10139416838611429657,
"detailed_name": "template<> struct type_trait<int> {}",
"qual_name_offset": 18,
"short_name": "type_trait",
"spell": "6:20-6:30|6:1-8:2|2|-1",
"bases": [4001289545226345448],
"funcs": [],
"types": [],
"vars": [],
"alias_of": 0,
"kind": 5,
"parent_kind": 1,
"declarations": [],
"derived": [],
"instances": [],
"uses": []
}, {
"usr": 10306412732558468540,
"detailed_name": "T2",
"qual_name_offset": 0,
"short_name": "",
"bases": [],
"funcs": [],
"types": [],
"vars": [],
"alias_of": 0,
"kind": 26,
"parent_kind": 0,
"declarations": ["23:27-23:29|23:21-23:29|1|-1"],
"derived": [],
"instances": [],
"uses": ["24:76-24:78|4|-1"]
}, {
"usr": 11072669167287398027,
"detailed_name": "namespace ns {}",
"qual_name_offset": 10,
"short_name": "ns",
"bases": [],
"funcs": [],
"types": [368613743269466510],
"vars": [{
"L": 7075924720131397743,
"R": -1
}],
"alias_of": 0,
"kind": 3,
"parent_kind": 0,
"declarations": ["18:11-18:13|18:1-21:2|1|-1"],
"derived": [],
"instances": [],
"uses": ["24:32-24:34|4|-1"]
}, {
"usr": 13813325012676356715,
"detailed_name": "T",
"qual_name_offset": 0,
"short_name": "",
"bases": [],
"funcs": [],
"types": [],
"vars": [],
"alias_of": 0,
"kind": 26,
"parent_kind": 0,
"declarations": ["2:17-2:18|2:11-2:18|1025|-1"],
"derived": [],
"instances": [],
"uses": []
}],
"usr2var": [{
"usr": 3643386974125063532,
"detailed_name": "static const bool type_trait::value",
"qual_name_offset": 18,
"short_name": "value",
"hover": "static const bool type_trait::value = false",
"type": 436,
"kind": 8,
"parent_kind": 23,
"storage": 2,
"declarations": ["3:21-3:26|3:3-3:34|1025|-1"],
"uses": ["11:31-11:36|4|-1"]
}, {
"usr": 4683419091429829178,
"detailed_name": "static const bool type_trait<int>::value",
"qual_name_offset": 18,
"short_name": "value",
"hover": "static const bool type_trait<int>::value = true",
"type": 436,
"kind": 8,
"parent_kind": 5,
"storage": 2,
"declarations": ["7:21-7:26|7:3-7:33|1025|-1"],
"uses": []
}, {
"usr": 7075924720131397743,
"detailed_name": "int ns::ConInNamespace",
"qual_name_offset": 4,
"short_name": "ConInNamespace",
"hover": "int ns::ConInNamespace = sizeof(T) > 4",
"spell": "20:9-20:23|20:1-20:39|1026|-1",
"type": 452,
"kind": 13,
"parent_kind": 3,
"storage": 0,
"declarations": [],
"uses": ["24:36-24:50|4|-1"]
}, {
"usr": 8419381068906673567,
"detailed_name": "int ConTwoTemplateParams",
"qual_name_offset": 4,
"short_name": "ConTwoTemplateParams",
"hover": "int ConTwoTemplateParams = ns::ConInNamespace<T1> && ConWithLogicalAnd<T2>",
"spell": "24:9-24:29|24:1-24:79|2|-1",
"type": 452,
"kind": 13,
"parent_kind": 1,
"storage": 0,
"declarations": [],
"uses": []
}, {
"usr": 15197037962155352994,
"detailed_name": "int ConWithLogicalAnd",
"qual_name_offset": 4,
"short_name": "ConWithLogicalAnd",
"hover": "int ConWithLogicalAnd = Con1<T> && sizeof(T) > sizeFunc()",
"spell": "16:9-16:26|16:1-16:62|2|-1",
"type": 452,
"kind": 13,
"parent_kind": 1,
"storage": 0,
"declarations": [],
"uses": ["24:58-24:75|4|-1"]
}, {
"usr": 15611304989063975809,
"detailed_name": "int Con1",
"qual_name_offset": 4,
"short_name": "Con1",
"hover": "int Con1 = type_trait<T>::value",
"spell": "11:9-11:13|11:1-11:36|2|-1",
"type": 452,
"kind": 13,
"parent_kind": 1,
"storage": 0,
"declarations": [],
"uses": ["16:29-16:33|4|-1"]
}]
}
*/

View File

@ -88,7 +88,11 @@ struct Config {
// ["-fopenmp", "-m*", "-Wall"].
std::vector<std::string> excludeArgs;
// Additional arguments to pass to clang.
// Arguments to be inserted after the compiler driver name. These serve as default arguments that can be overridden
// by user-provided arguments.
std::vector<std::string> prependArgs;
// Additional arguments to be appended at the end of the argument list.
std::vector<std::string> extraArgs;
// Translate absolute paths in compile_commands.json entries, .ccls options
@ -329,7 +333,7 @@ REFLECT_STRUCT(Config::ServerCap::DocumentOnTypeFormattingOptions, firstTriggerC
REFLECT_STRUCT(Config::ServerCap::Workspace::WorkspaceFolders, supported, changeNotifications);
REFLECT_STRUCT(Config::ServerCap::Workspace, workspaceFolders);
REFLECT_STRUCT(Config::ServerCap, documentOnTypeFormattingProvider, foldingRangeProvider, workspace);
REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, pathMappings, resourceDir);
REFLECT_STRUCT(Config::Clang, excludeArgs, prependArgs, extraArgs, pathMappings, resourceDir);
REFLECT_STRUCT(Config::ClientCapability, diagnosticsRelatedInformation, hierarchicalDocumentSymbolSupport, linkSupport,
snippetSupport);
REFLECT_STRUCT(Config::CodeLens, localVariables);

View File

@ -127,6 +127,7 @@ Kind getKind(const Decl *d, SymbolKind &kind) {
case Decl::NamespaceAlias:
kind = SymbolKind::Namespace;
return Kind::Type;
case Decl::Concept:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCImplementation:
@ -324,6 +325,9 @@ try_again:
switch (tp->getTypeClass()) {
case Type::Typedef:
d = cast<TypedefType>(tp)->getDecl();
tp = cast<TypedefType>(tp)->getDecl()->getUnderlyingType().getTypePtrOrNull();
if (tp)
goto try_again;
break;
case Type::ObjCObject:
d = cast<ObjCObjectType>(tp)->getInterface();
@ -360,9 +364,11 @@ try_again:
// FIXME: Template type parameters!
#if LLVM_VERSION_MAJOR < 22 // llvmorg-22-init-3166-g91cdd35008e9
case Type::Elaborated:
tp = cast<ElaboratedType>(tp)->getNamedType().getTypePtrOrNull();
goto try_again;
#endif
default:
break;
@ -1262,7 +1268,7 @@ IndexResult index(WorkingFiles *wfiles, VFS *vfs, const std::string &opt_wdir, c
clang->setInvocation(std::move(ci));
#endif
clang->createDiagnostics(
#if LLVM_VERSION_MAJOR >= 20
#if LLVM_VERSION_MAJOR >= 20 && LLVM_VERSION_MAJOR < 22
*fs,
#endif
&dc, false);
@ -1275,7 +1281,12 @@ IndexResult index(WorkingFiles *wfiles, VFS *vfs, const std::string &opt_wdir, c
if (!clang->hasTarget())
return {};
clang->getPreprocessorOpts().RetainRemappedFileBuffers = true;
#if LLVM_VERSION_MAJOR >= 22
clang->setVirtualFileSystem(fs);
clang->createFileManager();
#else
clang->createFileManager(fs);
#endif
clang->setSourceManager(new SourceManager(clang->getDiagnostics(), clang->getFileManager(), true));
IndexParam param(*vfs, no_linkage);

View File

@ -345,7 +345,11 @@ void do_initialize(MessageHandler *m, InitializeParam &param, ReplyOnce &reply)
if (g_config->cache.directory.size()) {
SmallString<256> path(g_config->cache.directory);
#if LLVM_VERSION_MAJOR >= 22
sys::path::make_absolute(project_path, path);
#else
sys::fs::make_absolute(project_path, path);
#endif
// Use upper case for the Driver letter on Windows.
g_config->cache.directory = normalizePath(path.str());
ensureEndsInSlash(g_config->cache.directory);

View File

@ -490,14 +490,22 @@ Project::Entry Project::findEntry(const std::string &path, bool can_redirect, bo
for (const std::string &arg : g_config->clang.extraArgs)
ret.args.push_back(intern(arg));
ret.args.push_back(intern("-working-directory=" + ret.directory));
if (g_config->clang.prependArgs.size()) {
std::vector<const char *> args;
for (StringRef arg : g_config->clang.prependArgs)
args.push_back(intern(arg));
ret.args.insert(ret.args.begin() + 1, args.begin(), args.end());
}
return ret;
}
void Project::index(WorkingFiles *wfiles, const RequestId &id) {
auto &gi = g_config->index;
GroupMatch match(gi.whitelist, gi.blacklist), match_i(gi.initialWhitelist, gi.initialBlacklist);
std::vector<const char *> args, extra_args;
for (const std::string &arg : g_config->clang.extraArgs)
std::vector<const char *> args, prepend_args, extra_args;
for (StringRef arg : g_config->clang.prependArgs)
prepend_args.push_back(intern(arg));
for (StringRef arg : g_config->clang.extraArgs)
extra_args.push_back(intern(arg));
{
std::lock_guard lock(mtx);
@ -510,6 +518,7 @@ void Project::index(WorkingFiles *wfiles, const RequestId &id) {
args = entry.args;
args.insert(args.end(), extra_args.begin(), extra_args.end());
args.push_back(intern("-working-directory=" + entry.directory));
args.insert(args.begin() + 1, prepend_args.begin(), prepend_args.end());
pipeline::index(entry.filename, args, interactive ? IndexMode::Normal : IndexMode::Background, false, id);
} else {
LOG_V(1) << "[" << i << "/" << folder.entries.size() << "]: " << reason << "; skip " << entry.filename;
@ -529,8 +538,10 @@ void Project::indexRelated(const std::string &path) {
auto &gi = g_config->index;
GroupMatch match(gi.whitelist, gi.blacklist);
StringRef stem = sys::path::stem(path);
std::vector<const char *> args, extra_args;
for (const std::string &arg : g_config->clang.extraArgs)
std::vector<const char *> args, prepend_args, extra_args;
for (StringRef arg : g_config->clang.prependArgs)
prepend_args.push_back(intern(arg));
for (StringRef arg : g_config->clang.extraArgs)
extra_args.push_back(intern(arg));
std::lock_guard lock(mtx);
for (auto &[root, folder] : root2folder)
@ -540,6 +551,7 @@ void Project::indexRelated(const std::string &path) {
args = entry.args;
args.insert(args.end(), extra_args.begin(), extra_args.end());
args.push_back(intern("-working-directory=" + entry.directory));
args.insert(args.begin() + 1, prepend_args.begin(), prepend_args.end());
if (sys::path::stem(entry.filename) == stem && entry.filename != path && match.matches(entry.filename, &reason))
pipeline::index(entry.filename, args, IndexMode::Background, true);
}

View File

@ -268,7 +268,7 @@ std::unique_ptr<CompilerInstance> buildCompilerInstance(Session &session, std::u
clang->setInvocation(std::move(ci));
#endif
clang->createDiagnostics(
#if LLVM_VERSION_MAJOR >= 20
#if LLVM_VERSION_MAJOR >= 20 && LLVM_VERSION_MAJOR < 22
*fs,
#endif
&dc, false);
@ -283,7 +283,12 @@ std::unique_ptr<CompilerInstance> buildCompilerInstance(Session &session, std::u
// Construct SourceManager with UserFilesAreVolatile: true because otherwise
// RequiresNullTerminator: true may cause out-of-bounds read when a file is
// mmap'ed but is saved concurrently.
#if LLVM_VERSION_MAJOR >= 22
clang->setVirtualFileSystem(fs);
clang->createFileManager();
#else
clang->createFileManager(fs);
#endif
clang->setSourceManager(new SourceManager(clang->getDiagnostics(), clang->getFileManager(), true));
auto &isec = clang->getFrontendOpts().Inputs;
if (isec.size()) {