ycm-core / YouCompleteMe

A code-completion engine for Vim
http://ycm-core.github.io/YouCompleteMe/
GNU General Public License v3.0
25.43k stars 2.81k forks source link

YCM shows diagnostic "'_POSIX_C_SOURCE' macro redefined" when editing C code. #3073

Closed shunlir closed 5 years ago

shunlir commented 6 years ago

Issue Prelude

Please complete these steps and check these boxes (by putting an x inside the brackets) before filing your issue:

Thank you for adhering to this process! It ensures your issue is resolved quickly and that neither your nor our time is needlessly wasted.

Issue Details

In C language Real-time diagnostic display feature, YCM incorrectly shows the following warning messages:

a.c|2 col 9 warning| '_POSIX_C_SOURCE' macro redefined

  1. create an empty directory test, add a CMakeLists.txt with the following contents:

    project(test) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GNU_SOURCE -D_POSIX_C_SOURCE=199506L -std=c99 -Wall") set(${PROJECT_NAME}_sources a.c) add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_sources})

  2. create a.c with the following content: #include <stdlib.h>; int main(int argc, char **argv) { (void)argc; (void)argv; return 0; }

  3. Open a.c with VIM, the following warning shows up:

    a.c|2 col 9 warning| '_POSIX_C_SOURCE' macro redefined

Should be no warning about _POSIX_C_SOURCE redefined.

Diagnostic data

Output of vim --version

VIM - Vi IMproved 8.1 (2018 May 18, compiled Jul 6 2018 08:05:07) Included patches: 1-155 Modified by pkg-vim-maintainers@lists.alioth.debian.org Compiled by pkg-vim-maintainers@lists.alioth.debian.org Huge version without GUI. Features included (+) or not (-): +acl +farsi +mouse_sgr -tag_any_white +arabic +file_in_path -mouse_sysmouse -tcl +autocmd +find_in_path +mouse_urxvt +termguicolors -autoservername +float +mouse_xterm +terminal -balloon_eval +folding +multi_byte +terminfo +balloon_eval_term -footer +multi_lang +termresponse -browse +fork() -mzscheme +textobjects ++builtin_terms +gettext +netbeans_intg +timers +byte_offset -hangul_input +num64 +title +channel +iconv +packages -toolbar +cindent +insert_expand +path_extra +user_commands -clientserver +job -perl +vartabs -clipboard +jumplist +persistent_undo +vertsplit +cmdline_compl +keymap +postscript +virtualedit +cmdline_hist +lambda +printer +visual +cmdline_info +langmap +profile +visualextra +comments +libcall -python +viminfo +conceal +linebreak +python3 +vreplace +cryptv +lispindent +quickfix +wildignore +cscope +listcmds +reltime +wildmenu +cursorbind +localmap +rightleft +windows +cursorshape -lua -ruby +writebackup +dialog_con +menu +scrollbind -X11 +diff +mksession +signs -xfontset +digraphs +modify_fname +smartindent -xim -dnd +mouse +startuptime -xpm -ebcdic -mouseshape +statusline -xsmp +emacs_tags +mouse_dec -sun_workshop -xterm_clipboard +eval +mouse_gpm +syntax -xterm_save +ex_extra -mouse_jsbterm +tag_binary
+extra_search +mouse_netterm +tag_old_static
system vimrc file: "$VIM/vimrc" user vimrc file: "$HOME/.vimrc" 2nd user vimrc file: "~/.vim/vimrc" user exrc file: "$HOME/.exrc" defaults file: "$VIMRUNTIME/defaults.vim" fall-back for $VIM: "/usr/share/vim" Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -Wdate-time -g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: gcc -Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -o vim -lm -ltinfo -lnsl -lselinux -lacl -lattr -lgpm -ldl -L/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu -lpython3.5m -lpthread -ldl -lutil -lm

Output of YcmDebugInfo

Printing YouCompleteMe debug information... -- Client logfile: /tmp/ycm_h_jb9qbs.log -- Server Python interpreter: /usr/bin/python -- Server Python version: 2.7.12 -- Server has Clang support compiled in: True -- Clang version: clang version 6.0.0 (tags/RELEASE_600/final) -- No extra configuration file found -- C-family completer debug information: -- Compilation database path: /home/shunlir/test_proj -- Flags: [u'/usr/bin/clang-5.0', u'-D_GNU_SOURCE', u'-D_POSIX_C_SOURCE=199506L', u'-std=c99', u'-Wall', u'-resource-dir=/home/shunlir/.vim/plugged/YouCompleteMe/third_party/ycmd/ycmd/../ clang_includes', u'-fspell-checking'] -- Translation unit: /home/shunlir/test_proj/a.c -- Server running at: http://127.0.0.1:50285 -- Server process ID: 28846 -- Server logfiles: -- /tmp/ycmd_50285_stdout_eomzrldt.log -- /tmp/ycmd_50285_stderr_f3f9ba8s.log

Contents of YCM, ycmd and completion engine logfiles

https://gist.github.com/shunlir/97f781ec223dd88e5e09ac145994ae0a

OS version, distribution, etc.

Distributor ID: Ubuntu Description: Ubuntu 16.04.3 LTS Release: 16.04 Codename: xenial

bstaletic commented 6 years ago

That's because you are redefining that symbol. It's defined in /usr/include/features.h and trasitively included if you include any standard header at all. If you really need to redefine that symbol, you should first undefine it with -U_POSIX_C_SOURCE.

bstaletic commented 6 years ago

You can check what is defined with $CC $CFLAGS -dM -E.

EDIT: It looks like the standard include headers do define _POSIX_C_SOURCE if you pass -D_GNU_SOURCE.

micbou commented 6 years ago

While it's true that _POSIX_C_SOURCE is defined twice, the redefinition occurs in a system header and shouldn't be reported. Here's a minimal test case that reproduces the issue:

foo.c

#include <foo.h>

include/foo.h

#define TEST 1

.ycm_extra_conf.py

def FlagsForFile( filename ):
  return { 'flags': [ '-isystem', 'include', '-DTEST=2' ] }

Edit foo.c, load the .ycm_extra_conf.py file, and type the command :YcmDiags. The diagnostic

/path/to/minimal/test/case|1 col 9 warning| 'TEST' macro redefined

is returned.

I wrote a small program that directly call the libclang API and display the list of diagnostics for a given file using the flags defined in the .ycm_extra_conf.py file above. Compiling that program and running it on foo.c returns the same diagnostic (without a file path):

file none line 1 column 9 'TEST' macro redefined

so it seems to be an issue with libclang, not YCM.

shunlir commented 6 years ago

@bstaletic I checked /usr/include/features.h on my system, _POSIX_C_SOURCE is conditionally #undef-ed then #define-ed:

#ifdef _GNU_SOURCE
...
# undef  _POSIX_C_SOURCE
# define _POSIX_C_SOURCE    200809L
...
#endif

Why is there warning about this kind of redefinition? Quote from gcc's document:

Once a macro has been undefined, that identifier may be redefined as a macro by a subsequent ‘#define’ directive. The new definition need not have any resemblance to the old definition.

The issue can also be simply reproduced with non-standard header file (modification from @micbou 's test case): foo.c:

#include "foo.h"

include/foo.h:

#ifdef TEST1
#undef TEST2
#define TEST2 9
#endif

.ycm_extra_conf.py:

def FlagsForFile( filename ):
  return { 'flags': [ '-isystem', 'include', '-DTEST1=1', '-DTEST2=2' ] }

Edit foo.c, load the .ycm_extra_conf.py file, and type the command :YcmDiags. The diagnostic:

foo.c|2 col 9 warning| 'TEST2' macro redefined
micbou commented 6 years ago

The issue doesn't occur if the translation unit is not parsed with the CXTranslationUnit_PrecompiledPreamble option. I think what happens is that when this option is enabled, libclang caches the preprocessor directives and in particular the macro definitions. When reparsing the file, if one of those macros is defined in the flags, libclang complains that it is redefined since it's already set in the cache.

micbou commented 6 years ago

Reported the issue to LLVM bug tracker: https://bugs.llvm.org/show_bug.cgi?id=38094.

bstaletic commented 5 years ago

Since this is a clang bug, we can close this.