ale/ale_linters/c/cc.vim

54 lines
1.6 KiB
VimL
Raw Normal View History

2016-10-03 18:55:55 +00:00
" Author: w0rp <devw0rp@gmail.com>
" Description: A C compiler linter for C files with gcc/clang, etc.
2016-10-03 18:55:55 +00:00
call ale#Set('c_cc_executable', '<auto>')
call ale#Set('c_cc_options', '-std=c11 -Wall')
function! ale_linters#c#cc#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'c_cc_executable')
" Default to either clang or gcc.
if l:executable is# '<auto>'
if ale#engine#IsExecutable(a:buffer, 'clang')
let l:executable = 'clang'
else
let l:executable = 'gcc'
endif
endif
return l:executable
endfunction
function! ale_linters#c#cc#GetCommand(buffer, output) abort
let l:cflags = ale#c#GetCFlags(a:buffer, a:output)
let l:ale_flags = ale#Var(a:buffer, 'c_cc_options')
Avoid overriding parsed C/C++ -std=* flag ALE appends flags from {c,cpp}_{clang,gcc}_options after those found by parsing compile_commands.json or Makefile output. If -std=* flags are present in both the ALE flags and parsed flags, the last one present (i.e., ALE's -std=* flag) will determine the mode the compiler works in. This can result in errors showing up in vim but not in the actual build or vice-versa. For example, say you have foo.cpp: #include <type_traits> int main() { return std::is_same_v<float, int>; } If cpp_clang_options contains -std=c++17 and -std=c++14 is parsed from compile_commands.json, then ALE would end up running something like: clang++ -S -x c++ -fsyntax-only -std=c++14 -std=c++17 - < foo.cpp This would result in no errors showing up in Vim, but the actual build would fail with: <stdin>:3:14: error: no template named 'is_same_v' in namespace 'std'; did you mean 'is_same'? return std::is_same_v<float, int>; ~~~~~^~~~~~~~~ is_same /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/type_traits:872:61: note: 'is_same' declared here template <class _Tp, class _Up> struct _LIBCPP_TEMPLATE_VIS is_same : public false_type {}; ^ <stdin>:3:35: error: expected '(' for function-style cast or type construction return std::is_same_v<float, int>; ~~~~~~~~~~~~~~~~~~~~~~~~~~^ 2 errors generated. as the actual build would not have the -std=c++17 flag added by ALE. If cpp_clang_options contains -std=c++14 and -std=c++17 is parsed from compile_commands.json, then the opposite problem would occur. ALE would end up running something like: clang++ -S -x c++ -fsyntax-only -std=c++17 -std=c++14 - < foo.cpp and would show an error on line 3 of foo.cpp: [clang] No template named 'is_same_v' in namespace 'std'; did you mean 'is_same'? (fix available) The actual build, on the other hand, would succeed without any complaints. Removing -std=* from ALE's flags if it is already present in the parsed flags ensures that the wrong -std=* flag is not used. An alternative would have been to switch the order in which parsed flags and ALE flags were concatenated when producing the command to execute, but that could prevent a user from intentionally using ALE's flags to override some other flags, e.g. -W* flags to enable/disable warnings in a project whose flags are not under the developer's control. -std=* flags are also present in cuda/nvcc.vim, objc/clang.vim, objcpp/clang.vim, and vhdl/ghdl.vim, but none of those linters appear to parse compile_commands.json or `make` output.
2020-03-17 22:00:47 +00:00
if l:cflags =~# '-std='
let l:ale_flags = substitute(
\ l:ale_flags,
\ '-std=\(c\|gnu\)[0-9]\{2\}',
\ '',
\ 'g')
endif
" -iquote with the directory the file is in makes #include work for
" headers in the same directory.
"
" `-o /dev/null` or `-o null` is needed to catch all errors,
" -fsyntax-only doesn't catch everything.
return '%e -S -x c'
\ . ' -o ' . g:ale#util#nul_file
\ . ' -iquote %s:h'
\ . ale#Pad(l:cflags)
Avoid overriding parsed C/C++ -std=* flag ALE appends flags from {c,cpp}_{clang,gcc}_options after those found by parsing compile_commands.json or Makefile output. If -std=* flags are present in both the ALE flags and parsed flags, the last one present (i.e., ALE's -std=* flag) will determine the mode the compiler works in. This can result in errors showing up in vim but not in the actual build or vice-versa. For example, say you have foo.cpp: #include <type_traits> int main() { return std::is_same_v<float, int>; } If cpp_clang_options contains -std=c++17 and -std=c++14 is parsed from compile_commands.json, then ALE would end up running something like: clang++ -S -x c++ -fsyntax-only -std=c++14 -std=c++17 - < foo.cpp This would result in no errors showing up in Vim, but the actual build would fail with: <stdin>:3:14: error: no template named 'is_same_v' in namespace 'std'; did you mean 'is_same'? return std::is_same_v<float, int>; ~~~~~^~~~~~~~~ is_same /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/type_traits:872:61: note: 'is_same' declared here template <class _Tp, class _Up> struct _LIBCPP_TEMPLATE_VIS is_same : public false_type {}; ^ <stdin>:3:35: error: expected '(' for function-style cast or type construction return std::is_same_v<float, int>; ~~~~~~~~~~~~~~~~~~~~~~~~~~^ 2 errors generated. as the actual build would not have the -std=c++17 flag added by ALE. If cpp_clang_options contains -std=c++14 and -std=c++17 is parsed from compile_commands.json, then the opposite problem would occur. ALE would end up running something like: clang++ -S -x c++ -fsyntax-only -std=c++17 -std=c++14 - < foo.cpp and would show an error on line 3 of foo.cpp: [clang] No template named 'is_same_v' in namespace 'std'; did you mean 'is_same'? (fix available) The actual build, on the other hand, would succeed without any complaints. Removing -std=* from ALE's flags if it is already present in the parsed flags ensures that the wrong -std=* flag is not used. An alternative would have been to switch the order in which parsed flags and ALE flags were concatenated when producing the command to execute, but that could prevent a user from intentionally using ALE's flags to override some other flags, e.g. -W* flags to enable/disable warnings in a project whose flags are not under the developer's control. -std=* flags are also present in cuda/nvcc.vim, objc/clang.vim, objcpp/clang.vim, and vhdl/ghdl.vim, but none of those linters appear to parse compile_commands.json or `make` output.
2020-03-17 22:00:47 +00:00
\ . ale#Pad(l:ale_flags) . ' -'
endfunction
call ale#linter#Define('c', {
\ 'name': 'cc',
\ 'aliases': ['gcc', 'clang'],
\ 'output_stream': 'stderr',
\ 'executable': function('ale_linters#c#cc#GetExecutable'),
\ 'command': {b -> ale#c#RunMakeCommand(b, function('ale_linters#c#cc#GetCommand'))},
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
\})