Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

static_assert error crashes YCM #2364

Closed
11 tasks done
mikelui opened this issue Oct 3, 2016 · 11 comments
Closed
11 tasks done

static_assert error crashes YCM #2364

mikelui opened this issue Oct 3, 2016 · 11 comments

Comments

@mikelui
Copy link

mikelui commented Oct 3, 2016

Issue Prelude

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

  • I have read and understood YCM's CONTRIBUTING document.
  • I have read and understood YCM's CODE_OF_CONDUCT document.
  • I have read and understood YCM's README, especially the
    Frequently Asked Questions section.
  • I have searched YCM's issue tracker to find issues similar to the one I'm
    about to report and couldn't find an answer to my problem. (Example Google
    search.
    )
  • If filing a bug report, I have included the output of vim --version.
  • If filing a bug report, I have included the output of :YcmDebugInfo.
  • If filing a bug report, I have included the output of
    :YcmToggleLogs stderr.
  • If filing a bug report, I have included which OS (including specific OS
    version) I am using.
  • If filing a bug report, I have included a minimal test case that reproduces
    my issue.
  • I understand this is an open-source project staffed by volunteers and
    that any help I receive is a selfless, heartfelt gift of their free time. I
    know I am not entitled to anything and will be polite and courteous.
  • I understand my issue may be closed if it becomes obvious I didn't
    actually perform all of these steps.

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

[If filing a bug report, please include a list of steps that describe how to
reproduce the bug you are experiencing. Also include test code if relevant.]

The following example crashes YCM in vim (did a :PluginUpdate and recompile just before reporting the issue)

#include <iostream>                                                                                 

template<int N>                                                                                     
struct Test                                                                                         
{                                                                                                   
    Test() {                                                                                        
        static_assert(N >= 0);                                                                      
        std::cout << N << std::endl;                                                                
    }                                                                                               
};                                                                                                  

:YcmDiags

Forcing compilation, this will block Vim until done.
Error detected while processing function <SNR>72_ShowDiagnostics[1]..<SNR>72_ForceCompile:
line    9:
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "~/.vim/bundle/YouCompleteMe/autoload/../python/ycm/youcompleteme.py", line 558, in HandleFileParseRequest
    self._latest_diagnostics = self._latest_file_parse_request.Response()
  File "~/.vim/bundle/YouCompleteMe/autoload/../python/ycm/client/event_notification.py", line 65, in Response
    self._cached_response = JsonFromFuture( self._response_future )
  File "~/.vim/bundle/YouCompleteMe/autoload/../python/ycm/client/base_request.py", line 173, in JsonFromFuture
    response = future.result()
  File "~/.vim/bundle/YouCompleteMe/third_party/pythonfutures/concurrent/futures/_base.py", line 404, in result
    return self.__get_result()
  File "~/.vim/bundle/YouCompleteMe/third_party/pythonfutures/concurrent/futures/_base.py", line 356, in __get_result
    raise self._exception
requests.exceptions.ConnectionError: ('Connection aborted.', BadStatusLine("''",))
No warnings or errors detected
Press ENTER or type command to continue

The following example DOES NOT crash YCM (no errors)

#include <iostream>                                                                                 

template<int N>                                                                                     
struct Test                                                                                         
{                                                                                                   
    Test() {                                                                                        
        static_assert(N >= 0, "N too small");                                                                      
        std::cout << N << std::endl;                                                                
    }                                                                                               
};                                                                                                  

:YcmDiags

Forcing compilation, this will block Vim until done.
No warnings or errors detected
Press ENTER or type command to continue

Any other coding errors seem to be detected correctly in my current configuration.

$ vim --version

VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Sep 26 2016 10:00:18)
Included patches: 1-13
Compiled by Arch Linux
Huge version with GTK3 GUI.  Features included (+) or not (-):
+acl             +file_in_path    +mouse_sgr       +tag_old_static
+arabic          +find_in_path    -mouse_sysmouse  -tag_any_white
+autocmd         +float           +mouse_urxvt     +tcl/dyn
+balloon_eval    +folding         +mouse_xterm     +termguicolors
+browse          -footer          +multi_byte      +terminfo
++builtin_terms  +fork()          +multi_lang      +termresponse
+byte_offset     +gettext         -mzscheme        +textobjects
+channel         -hangul_input    +netbeans_intg   +timers
+cindent         +iconv           +num64           +title
+clientserver    +insert_expand   +packages        +toolbar
+clipboard       +job             +path_extra      +user_commands
+cmdline_compl   +jumplist        +perl/dyn        +vertsplit
+cmdline_hist    +keymap          +persistent_undo +virtualedit
+cmdline_info    +lambda          +postscript      +visual
+comments        +langmap         +printer         +visualextra
+conceal         +libcall         +profile         +viminfo
+cryptv          +linebreak       +python/dyn      +vreplace
+cscope          +lispindent      +python3/dyn     +wildignore
+cursorbind      +listcmds        +quickfix        +wildmenu
+cursorshape     +localmap        +reltime         +windows
+dialog_con_gui  +lua/dyn         +rightleft       +writebackup
+diff            +menu            +ruby/dyn        +X11
+digraphs        +mksession       +scrollbind      -xfontset
+dnd             +modify_fname    +signs           +xim
-ebcdic          +mouse           +smartindent     -xpm
+emacs_tags      +mouseshape      +startuptime     +xsmp_interact
+eval            +mouse_dec       +statusline      +xterm_clipboard
+ex_extra        +mouse_gpm       -sun_workshop    -xterm_save
+extra_search    -mouse_jsbterm   +syntax          
+farsi           +mouse_netterm   +tag_binary      
   system vimrc file: "/etc/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "/etc/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK  -pthread -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/harfbuzz -I/usr/include/libdrm -I/usr/include/libpng16 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -D_FORTIFY_SOURCE=2  -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1      
Linking: gcc   -L. -Wl,-O1,--sort-common,--as-needed,-z,relro -fstack-protector -rdynamic -Wl,-export-dynamic -Wl,-E -Wl,-rpath,/usr/lib/perl5/core_perl/CORE  -Wl,-O1,--sort-common,--as-needed,-z,relro -L/usr/local/lib -Wl,--as-needed -o vim   -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lSM -lICE -lXt -lX11 -lXdmcp -lSM -lICE  -lm -lncurses -lelf -lnsl    -lacl -lattr -lgpm -ldl   -Wl,-E -Wl,-rpath,/usr/lib/perl5/core_perl/CORE -Wl,-O1,--sort-common,--as-needed,-z,relro -fstack-protector-strong -L/usr/local/lib  -L/usr/lib/perl5/core_perl/CORE -lperl -lpthread -lnsl -ldl -lm -lcrypt -lutil -lc   -L/usr/lib -ltclstub8.6 -ldl -lz -lpthread -lieee -lm     

:YcmDebugInfo

Printing YouCompleteMe debug information...
-- Server crashed, no debug info from server
-- Server running at: http://127.0.0.1:40145
-- Server process ID: 30459
-- Server logfiles:
--   /tmp/ycm_temp/server_40145_stdout.log
--   /tmp/ycm_temp/server_40145_stderr.log
Press ENTER or type command to continue

:YcmToggleLogs stderr

2016-10-03 15:06:10,278 - DEBUG - Global extra conf not loaded or no function YcmCorePreload        
2016-10-03 15:06:11,899 - INFO - Received health request                                            
2016-10-03 15:06:11,906 - INFO - Received filetype completion available request                     
2016-10-03 15:06:22,183 - INFO - Received event notification                                        
2016-10-03 15:06:22,184 - DEBUG - Event name: BufferVisit    

I'm guessing the logs are minimal due to the server crashing.

On 64-bit ArchLinux

$ uname -a
4.7.5-1-ARCH #1 SMP PREEMPT Sat Sep 24 13:04:22 CEST 2016 x86_64 GNU/Linux

ycmd compiled with libclang 3.9 (./install.py --clang-completer).

If I compile the erroring code with my system clang (3.8.1) I get the correct error/warning message. Untested wtih clang 3.9.

$ clang -std=c++11 -c toy.cpp 

toy.cpp:7:29: warning: static_assert with no message is a C++1z extension [-Wc++1z-extensions]
        static_assert(N >= 0);
                            ^
                            , ""
1 warning generated.

Flags passed to libclang/ycm:

flags = [                                                                        
'-Wall',                                                                                                                                
'-std=c++11',                                                                          
'-x',                                                                            
'c++',                                                                           
]    
@puremourning
Copy link
Member

Thanks for the report. I can repro this crash.

I have found some crashes in libclang 3.9 myself recently. This might be related.

@puremourning
Copy link
Member

stack trace:

Thread 4 Crashed:
0   libclang.dylib                  0x000000010555df20 clang::cxcursor::MakeCXCursor(clang::Stmt const*, clang::Decl const*, CXTranslationUnitImpl*, clang::SourceRange) + 32
1   libclang.dylib                  0x0000000105534198 clang::declvisitor::Base<clang::declvisitor::make_ptr, clang::cxcursor::CursorVisitor, bool>::Visit(clang::Decl*) + 1672
2   libclang.dylib                  0x0000000105532366 clang::cxcursor::CursorVisitor::VisitChildren(CXCursor) + 358
3   libclang.dylib                  0x0000000105531a1e clang::cxcursor::CursorVisitor::Visit(CXCursor, bool) + 478
4   libclang.dylib                  0x000000010553b8cf clang::cxcursor::CursorVisitor::RunVisitorWorkList(llvm::SmallVector<clang::cxcursor::VisitorJob, 10u>&) + 2447
5   libclang.dylib                  0x00000001055344bc clang::cxcursor::CursorVisitor::Visit(clang::Stmt const*) + 204
6   libclang.dylib                  0x00000001055323af clang::cxcursor::CursorVisitor::VisitChildren(CXCursor) + 431
7   libclang.dylib                  0x0000000105531a1e clang::cxcursor::CursorVisitor::Visit(CXCursor, bool) + 478
8   libclang.dylib                  0x0000000105535d62 clang::cxcursor::CursorVisitor::VisitFunctionDecl(clang::FunctionDecl*) + 1506
9   libclang.dylib                  0x0000000105533b5a clang::declvisitor::Base<clang::declvisitor::make_ptr, clang::cxcursor::CursorVisitor, bool>::Visit(clang::Decl*) + 74
10  libclang.dylib                  0x0000000105532366 clang::cxcursor::CursorVisitor::VisitChildren(CXCursor) + 358
11  libclang.dylib                  0x0000000105531a1e clang::cxcursor::CursorVisitor::Visit(CXCursor, bool) + 478
12  libclang.dylib                  0x00000001055346ed clang::cxcursor::CursorVisitor::handleDeclForVisitation(clang::Decl const*) + 365
13  libclang.dylib                  0x0000000105534794 clang::cxcursor::CursorVisitor::VisitDeclContext(clang::DeclContext*) + 116
14  libclang.dylib                  0x00000001055352ef clang::cxcursor::CursorVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl*) + 207
15  libclang.dylib                  0x0000000105533d1f clang::declvisitor::Base<clang::declvisitor::make_ptr, clang::cxcursor::CursorVisitor, bool>::Visit(clang::Decl*) + 527
16  libclang.dylib                  0x0000000105532366 clang::cxcursor::CursorVisitor::VisitChildren(CXCursor) + 358
17  libclang.dylib                  0x0000000105533206 clang::cxcursor::CursorVisitor::visitDeclsFromFileRegion(clang::FileID, unsigned int, unsigned int) + 1222
18  libclang.dylib                  0x0000000105532abc clang::cxcursor::CursorVisitor::visitFileRegion() + 188
19  libclang.dylib                  0x00000001055432bb clang::cxcursor::getCursor(CXTranslationUnitImpl*, clang::SourceLocation) + 411
20  libclang.dylib                  0x00000001055428cd clang_getCursor + 77
21  ycm_core.so                     0x00000001052fb1bd YouCompleteMe::BuildDiagnostic(boost::shared_ptr<void>, CXTranslationUnitImpl*) + 653
22  ycm_core.so                     0x00000001053026d2 YouCompleteMe::TranslationUnit::UpdateLatestDiagnostics() + 1122
23  ycm_core.so                     0x0000000105300e62 YouCompleteMe::TranslationUnit::Reparse(std::__1::vector<UnsavedFile, std::__1::allocator<UnsavedFile> > const&) + 66
24  ycm_core.so                     0x00000001052f81ca YouCompleteMe::ClangCompleter::UpdateTranslationUnit(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<UnsavedFile, std::__1::allocator<UnsavedFile> > const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) + 90
25  ycm_core.so                     0x000000010533ce34 boost::python::detail::caller_arity<4u>::impl<std::__1::vector<YouCompleteMe::Diagnostic, std::__1::allocator<YouCompleteMe::Diagnostic> > (YouCompleteMe::ClangCompleter::*)(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<UnsavedFile, std::__1::allocator<UnsavedFile> > const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&), boost::python::default_call_policies, boost::mpl::vector5<std::__1::vector<YouCompleteMe::Diagnostic, std::__1::allocator<YouCompleteMe::Diagnostic> >, YouCompleteMe::ClangCompleter&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<UnsavedFile, std::__1::allocator<UnsavedFile> > const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&> >::operator()(_object*, _object*) + 372
26  ycm_core.so                     0x00000001053836ca boost::python::objects::function::call(_object*, _object*) const + 874
27  ycm_core.so                     0x00000001053857ea boost::detail::function::void_function_ref_invoker0<boost::python::objects::(anonymous namespace)::bind_return, void>::invoke(boost::detail::function::function_buffer&) + 26
28  ycm_core.so                     0x000000010537c961 boost::python::handle_exception_impl(boost::function0<void>) + 81
29  ycm_core.so                     0x0000000105385473 boost::python::objects::function_call(_object*, _object*, _object*) + 83

@puremourning
Copy link
Member

This is the diagnostic i think it should be reporting:

crash.cc:7:29: warning: static_assert with no message is a C++1z extension [-Wc++1z-extensions]
        static_assert(N >= 0);
                            ^
                            , ""

@puremourning
Copy link
Member

OK. I havre reproduced this in a debugger, and can confirm it is a libclang bug.

for the test file:

int main() {
   static_assert(false);
}

we hit an assert in libclang.

#931 ycmd.tests.clang.diagnostics_test.Diagnostic_Crash_test ... Assertion failed: (S && TU && "Invalid arguments!"), function MakeCXCursor, file /Users/ben/Development/llvm.git/tools/clang/tools/libclang/CXCursor.cpp, line 108.

relevant code snippets from ycmd:

   264    CXSourceLocation source_location =
   265      clang_getDiagnosticLocation( diagnostic );
...
   164    CXSourceRange range = clang_getCursorExtent(
-> 165                            clang_getCursor( translation_unit, source_location ) );

we are hitting this assert

-> 108 assert(S && TU && "Invalid arguments!”);
in
    105     CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
   106                                     CXTranslationUnit TU,
   107                                     SourceRange RegionOfInterest) {
 (lldb) print TU
(CXTranslationUnit) $13 = 0x00007fed4bd3c8c0
(lldb) print S
(const clang::Stmt *) $14 = 0x0000000000000000

Called from context:

   1243    bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) {
   1244      if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, RegionOfInterest)))
   1245        return true;
-> 1246      if (Visit(MakeCXCursor(D->getMessage(), StmtParent, TU, RegionOfInterest)))
   1247        return true;
   1248      return false;
   1249    }
 (lldb) print D
(clang::StaticAssertDecl *) $15 = 0x00007fed4c89f380
(lldb) print D->getMessage()
(clang::StringLiteral *) $16 = 0x0000000000000000

D->getMessage() is nullptr, because the test code isn't specifying the second argument to static_assert.

The diagnostic in question is actually warning that the second parameter being missing is a c++1z extension.

@d0k @r4nt thoughts? to raise this with clang team would we need a test case uniquely using libclang?

@puremourning
Copy link
Member

Also, kudos to lldb. That's some seriously good debugging power (once i got it working)

@puremourning
Copy link
Member

puremourning commented Oct 4, 2016

OK so the patch is trivial and fixes it.

(ycmd-3.5.1-debug) BeniMac:clang ben$ git diff
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 027bf95..4837018 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -1243,7 +1243,8 @@ bool CursorVisitor::VisitUnresolvedUsingTypenameDecl(
 bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) {
   if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, RegionOfInterest)))
     return true;
-  if (Visit(MakeCXCursor(D->getMessage(), StmtParent, TU, RegionOfInterest)))
+  if (D->getMessage() /* optional in c++1z */ &&
+      Visit(MakeCXCursor(D->getMessage(), StmtParent, TU, RegionOfInterest)))
     return true;
   return false;
 }

just need a test case.

ycmd test case that now "passes":

@IsolatedYcmd
def Diagnostic_Crash_test( app ):
  contents = ReadFile( PathToTestFile( 'crash.cc' ) )

  #import clewn.vim as clewn; clewn.pdb()
  event_data = BuildRequest( contents = contents,
                             event_name = 'FileReadyToParse',
                             filetype = 'cpp',
                             compilation_flags = [ '-x', 'c++', '-std=c++11' ] )

  response = app.post_json( '/event_notification', event_data ).json
  pprint( response )
  assert( False )
-------------------- >> begin captured stdout << ---------------------
[{'fixit_available': True,
  'kind': 'WARNING',
  'location': {'column_num': 22, 'filepath': '/foo', 'line_num': 2},
  'location_extent': {'end': {'column_num': 23,
                              'filepath': '/foo',
                              'line_num': 2},
                      'start': {'column_num': 22,
                                'filepath': '/foo',
                                'line_num': 2}},
  'ranges': [],
  'text': 'static_assert with no message is a C++1z extension'},
 {'fixit_available': False,
  'kind': 'ERROR',
  'location': {'column_num': 3, 'filepath': '/foo', 'line_num': 2},
  'location_extent': {'end': {'column_num': 16,
                              'filepath': '/foo',
                              'line_num': 2},
                      'start': {'column_num': 3,
                                'filepath': '/foo',
                                'line_num': 2}},
  'ranges': [{'end': {'column_num': 22, 'filepath': '/foo', 'line_num': 2},
              'start': {'column_num': 17, 'filepath': '/foo', 'line_num': 2}}],
  'text': 'static_assert failed'}]

--------------------- >> end captured stdout << ----------------------

@Valloric
Copy link
Member

Valloric commented Oct 4, 2016

@puremourning I want some of your superpowers. :D

@d0k
Copy link

d0k commented Oct 4, 2016

Looks like it was fixed upstream recently llvm-mirror/clang@e3a335e (sadly without a test case). Does it still reproduce with trunk libclang?

@puremourning
Copy link
Member

thanks @d0k will try now

@puremourning
Copy link
Member

@d0k thanks (sorry I should have checked), master does indeed fix it.

@mikelui I'd like to close this as not a YCM bug. We track the latest clang releases pretty much immediately after release so we will pick up this upstream fix as soon as it lands, and we're probably going to forget to mention this issue when we do :)

I do feel like we should handle these server crashes better however. The Vim tracebacks completely break the workflow which is against our whole principle. That said, that's sort of orthogonal to fixing this particular crash, and I know @micbou was looking at this a while back.

If you use this static_assert pattern a lot, then the best advice is to build a libclang against llvm master and follow the full installation instructions to use it with ycmd.

@puremourning
Copy link
Member

As mentioned, this is not a YCM bug, but an upstream one.

It can be worked around by building trunk clang and using the full installation instructions until such a time as the patch is released and we upgrade to that version of libclang.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 25, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants