Babbleshack
Babbleshack

Reputation: 341

Configure clang-check for c++ standard libraries

I am trying to run Ale as my linter, which in turn uses clang-check to lint my code.

$ clang-check FeatureManager.h
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "FeatureManager.h"
No compilation database found in /home/babbleshack/ or any parent directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
/home/babbleshack/FeatureManager.h:6:10: fatal error: 'unordered_map' file not found
#include <unordered_map>
         ^~~~~~~~~~~~~~~
1 error generated.
Error while processing /home/babbleshack/FeatureManager.h.

Whereas compiling with clang++ returns only a warning.

$ clang++ -std=c++11 -Wall FeatureManager.cxx FeatureManager.h
clang-5.0: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]

There are no flags to clang-check allowing me to set compilation flags.

Upvotes: 2

Views: 6466

Answers (2)

dimo414
dimo414

Reputation: 48874

I was getting stumped by a similar error message for far too long:

/my/project/src/util.h:4:10: error: 'string' file not found [clang-diagnostic-error]
#include <string>
         ^

I saw other questions suggesting that I was missing some critical package, but everything already seemed to be installed (and my code built just fine, it was only clang-tidy that was getting upset).

Passing -v showed that my .h file was being handled differently:

$ clang-tidy ... src/*.{h,cc} -- ... -v
...
clang-tool ... -main-file-name util.cc ... -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9 ... -x c++ ... /tmp/copy/src/util_test.cc
...
clang-tool ... -main-file-name util.h ... -x c-header /my/project/src/util.h
...

As Kris notes the key distinction is the -x c-header flag, which is because clang assumes a .h file contains C, not C++, and this in turn means that the system C++ includes weren't being used to process util.h.

But the -main-file-name flag also stood out to me as odd; why would a header file ever be the main file? While digging around I also came across this short but insightful answer that header files shouldn't be directly compiled in the first place! Using src/*.cc instead of src/*.{h,cc} avoids the problem entirely by never asking Clang to try to process a .h on its own in the first place!

This does introduce one more wrinkle, though. Errors in these header files won't be reported by default, since they're not the files you asked clang-tidy to look at. This is where the "Use -header-filter=. to display errors from all non-system headers.*" message clang-tidy prints comes in. If I pass -header-filter=src/.* (to only include my src headers and not any other header files I'm including with -I) I see the expected errors in my header files. Phew!

I'm not sure whether to prefer -x c++ or -header-filter=.* generally. A downside of -header-filter is you have to tune the filter regex, rather than just passing in the files you want to check. But on the other hand processing header files in isolation is essentially wasteful work (that I expect would add up quickly in a larger project).

Upvotes: 0

Kris Swann
Kris Swann

Reputation: 166

Took a while to figure this out, but you can do

clang-check file.cxx -- -Wall -std=c++11 -x c++

or if you are using clang-tidy

clang-tidy file.cxx -- -Wall -std=c++11 -x c++

To get both working with ALE, I added the following to my vimrc

let g:ale_cpp_clangtidy_options = '-Wall -std=c++11 -x c++' let g:ale_cpp_clangcheck_options = '-- -Wall -std=c++11 -x c++'

If you want ALE to work for C as well, you will have to do the same for g:ale_c_clangtidy_options and g:ale_c_clangcheck_options.

Upvotes: 15

Related Questions