From e5ec341a559b5f8153d5c3c376331ae4e24356c2 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 10 Nov 2018 16:18:27 -0800 Subject: [PATCH] Add header guard --- FAQ.md | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/FAQ.md b/FAQ.md index d9cf6c6..d3e2d25 100644 --- a/FAQ.md +++ b/FAQ.md @@ -60,13 +60,13 @@ In Emacs, it is: ### Project root detection -[emacs-ccls](https://github.com/MaskRay/emacs-cquery/) locates the project root with `ccls-project-root-matchers`: +[emacs-ccls](https://github.com/MaskRay/emacs-cquery/) locates the project root in the following order: * `.ccls-root`. If this file exists in any parent directory, that directory is treated as the project root. -* `(projectile-project-root)`. Then this function is called. You likely don't want `/usr/include/c++/8/algorithm` to be treated as in the project `/usr/include/c++/8/`, `(setq projectile-require-project-root t)` inhibits the behavior. +* `(lsp--suggest-project-root)` which in turn calls `(projectile-project-root)`. Usually you don't want `/usr/include/c++/8/algorithm` to be treated as in the project `/usr/include/c++/8/`, `(setq projectile-require-project-root t)` inhibits the behavior. The root directory is sent to ccls (the language server) through the `rootUri` field in the `initialize` request. -ccls finds `.ccls` or `compile_commands.json` in the directory. +ccls reads `.ccls` or `compile_commands.json` in the directory. If neither exists, ccls fallbacks to `%clang $path`. ``` proj @@ -80,7 +80,7 @@ proj ### Maximum number of file descriptors -When indexing ccls itself, some files require more than 1000 file descriptors. Remember to increase `RLIMIT_NOFILE`. +Some projects may require more than 1000 file descriptors. Remember to increase `RLIMIT_NOFILE`. ```zsh ulimit -n 32768 @@ -143,6 +143,37 @@ ccls will save a file in `cacheDirectory`: ... ``` +### Diagnostics in headers + +For efficiency, headers are compiled on their own (as if `clang [options] a.h`) to utilize Clang's preamble optimization. + +For headers that are not self-contained (e.g. some `/usr/include/bits/*.h` which require a predefined macro) ccls emits diagnostics that you don't see when building the project. + +```c +// a.c +#define M +#include "a.h" + +// a.h +#ifndef M +#error M not defined +#endif +``` + +One approach ccls explored before was to compile its import file `a.c`, but it caused severe performance issue for some projects. +For smaller files this does not matter and checking for a header guard may help the situation. + +### Multi-version headers + +A header can be included in different translation units with different compiler flags. It may behave differently via `#ifdef`. +Ideally there should be some mechanism to switch among different views (compiler flags) when you are editing the file. + +For efficiency, a header is only indexed with one set of compiler flags, so either the `#if` block or `#else` is indexed, the other is left blank. + +For macros, there is code to track different usage, thus you may find them able to jump to multiple targets. +`index.multiVersion` is an experimental option to index every version to certify that the author is aware of this issue :) +It may not be very useful though. It is of type `number` but not `boolean` as the author is also aware of other dimensions of the multi-version problem. + ### Definitions `textDocument/definition` can be used in many places. Some are current implementation details and may subject to change.