#include <iostream>
What do you think? I'll submit patches using the name 'Clang Code Completion' under color settings in 'settings->environment->colors'.
Oh, one more thing I forgot about. I had to add:Erm... why do we need iostream? Logging/debug logging should be directed through C::B's log manager.Codeto 'clangplugin.cpp' and 'translationunit.cpp' to build the plugin. I don't know why iostream were missing in those 2 files initially.#include <iostream>
I believe the main CC plugin already registers some colors; if possible, reuse those first.What do you think? I'll submit patches using the name 'Clang Code Completion' under color settings in 'settings->environment->colors'.No problem for me as long as Alpha0010 and the other nice C::B guys approve.
I may contribute some changes starting with the coloring of the information boxes but I'm not sure if each code completion plugin needs to have its own set of colors. I think they do because of the different coloring schemes for different languages. What do you think? I'll submit patches using the name 'Clang Code Completion' under color settings in 'settings->environment->colors'.Can you give better details what colour do you need to define?
Oh, one more thing I forgot about. I had to add:Erm... why do we need iostream? Logging/debug logging should be directed through C::B's log manager.Codeto 'clangplugin.cpp' and 'translationunit.cpp' to build the plugin. I don't know why iostream were missing in those 2 files initially.#include <iostream>
I believe the main CC plugin already registers some colors; if possible, reuse those first.What do you think? I'll submit patches using the name 'Clang Code Completion' under color settings in 'settings->environment->colors'.No problem for me as long as Alpha0010 and the other nice C::B guys approve.
Erm... why do we need iostream? Logging/debug logging should be directed through C::B's log manager.I had to include them because the compiler were spitting 'cout doesn't belong to namespace std' kind of errors. I think yvesdm3000 made it clear.
I believe the main CC plugin already registers some colors; if possible, reuse those first.As you wish. I also prefer to reuse the same colors but my reasoning was that the clang cc uses a different color for errors while the built-in cc doesn't have a designated color for that which might introduce color entries that are not used by some plugins. Also people may opt for different syntax highlighting for different languages making cc plugins for different languages less responsive in terms of colors. I think at least cc plugins for different languages should define their own colors.
Also people may opt for different syntax highlighting for different languages making cc plugins for different languages less responsive in terms of colors. I think at least cc plugins for different languages should define their own colors.If you ask me this is not a good idea.
I guess I've misunderstood you, because I thought that you're talking about some colours for errors. Ignore.
More tasks to do: the class&method toolbar, goto declaration/implementation context menus and something that replaces cscope.The current goto declaration/implementation is supplied by the build-in codecompletion plugin.
-Yves
yvesdm3000The standard CC is still maintained by some people, but it is hard to parse the template or C++11 new feature related code. :(
I had some difficulties compiling this plugin, but it's such a pleasure to use. Is there any chance to have it in codeblocks-contrib anytime soon? I mean the standard CC plugin is nothing but a source of infinite frustration.
while(/*! condition !*/){
}
The standard CC is still maintained by some people, but it is hard to parse the template or C++11 new feature related code. :(It has problems with all sorts of other stuff not related to C++11 (like this issue (http://forums.codeblocks.org/index.php/topic,20662.0.html)). I know it's a huge piece of work, but it has just never functioned properly for me with anything beyond helloworlds, and I'm very sorry about it. Even the plain notepad++ way of suggesting whatever it sees in the document without any language parsing is more helpful. Btw. notepad++ has more features working better, but it's a subject for a different topic.
More tasks to do: the class&method toolbar, goto declaration/implementation context menus and something that replaces cscope.If you accept feature suggestions, then I'd prefer to have context dependent syntax highlighting. Current highlighting schemes are plain based on a set of keywords. I'd like the highlighting to be able to differentiate between functions, variables, class names, preprocessor constants etc., which requires support of a syntax parsing plugin.
ollydbgI'd like to help on this issue.The standard CC is still maintained by some people, but it is hard to parse the template or C++11 new feature related code. :(It has problems with all sorts of other stuff not related to C++11 (like this issue (http://forums.codeblocks.org/index.php/topic,20662.0.html)).
yvesdm3000You may look at this plugin: Semantic highlight (http://forums.codeblocks.org/index.php/topic,16249.0.html) which also uses clang.More tasks to do: the class&method toolbar, goto declaration/implementation context menus and something that replaces cscope.If you accept feature suggestions, then I'd prefer to have context dependent syntax highlighting. Current highlighting schemes are plain based on a set of keywords. I'd like the highlighting to be able to differentiate between functions, variables, class names, preprocessor constants etc., which requires support of a syntax parsing plugin.
Another feature is to provide suggestions in a relevance-based order. I.e. when passing arguments to a function, the first suggestion should be a local variable name or an argument of a currently edited function that has the type most compatible with the currently passed argument, and further suggestions should include other castable identifiers in order of how forceful the casting should be.
These two would make it close to the level of VisualAssistX.
You may look at this plugin: Semantic highlight (http://forums.codeblocks.org/index.php/topic,16249.0.html) which also uses clang.
Also people may opt for different syntax highlighting for different languages making cc plugins for different languages less responsive in terms of colors. I think at least cc plugins for different languages should define their own colors.If you ask me this is not a good idea.
Generally I try to make all languages look roughly the same.
What error color are we talking about, because I've not tried this plugin yet?
I'll look into setting up a VM that could make a binary out of the plugin automatically after each push. I guess it should follow the weekly nightly builds and on what wxWindows version should it be built ?Currently, Windows C::B nightly build use wx2.8.12, see here:
And I guess people will want Linux+Windows? And then also a binary of Clang I suppose ?I think a binary of Clang is necessary. (At least under Windows OS)
For Linux maybe an Ubuntu 15.10 with the distro's version of Clang?
-Yves
I'd like to help on this issue.Thanks for taking a look. Unfortunately I am able to reproduce the bug in Fedora only.
Is the test code you supplied only works under Linux system?
You may look at this plugin: Semantic highlight (http://forums.codeblocks.org/index.php/topic,16249.0.html) which also uses clang.Well, thank you for the hint. Though this would make up already two plugins doing the same intensive background parsing. It's much more preferable to have this functionality in a single one. But I see... the same thought is already present in the topic. :-)
Maybe I should make a merge from this plugin into the CC-plugin, just to make sure the same file is not parsed twice...Nope don't do it. This is something that should be done in the sdk and the cc plugins should only feed it with data.
For now I see that the inline Clang warning/error annotations have unconfigurable colours, style number 50. I guess Alpha0010 just chose a number ?I am aware of that but I couldn't locate the piece of code that configures this yet. Can someone point me to the code in question so I can take care of that too?
-Yves
MSYS2 project already provides a clang binary. Only clang.dll is needed to build and use the plugin, actually this binary is what I'm using to build and test the plugin. Link here:QuoteAnd I guess people will want Linux+Windows? And then also a binary of Clang I suppose ?I think a binary of Clang is necessary. (At least under Windows OS)
For Linux maybe an Ubuntu 15.10 with the distro's version of Clang?
-Yves
Afaik the built-in cc plugin provides the semantic highlight for the data members currently. I use it and runs quite smooth and nice. I've even enhanced it a little further to color the class names also. I believe it won't hurt to implement this in clang plugin till it's implemented in sdk (which I don't think will ever happen though).Maybe I should make a merge from this plugin into the CC-plugin, just to make sure the same file is not parsed twice...Nope don't do it. This is something that should be done in the sdk and the cc plugins should only feed it with data.
As far as I know scintilla doesn't have easy way to implement this, so this is why we've not investigated much time.
Afaik the built-in cc plugin provides the semantic highlight for the data members currently. I use it and runs quite smooth and nice. I've even enhanced it a little further to color the class names also. I believe it won't hurt to implement this in clang plugin till it's implemented in sdk (which I don't think will ever happen though).The one in the CC is just a hack that breaks in too many ways (it is not context aware, it is just global). :)
Btw clang's documentation parser doesn't seem to be as good as the built-in cc plugin's, or is it?Yes, I ran into some annoying bugs in it (some comments fail to parse, sometimes clang dumps the entire file into a comment). However, the styling/generating of the output in this plugin is unfinished; some of the information that clang does provide (e.g. blocks @param, @return, ...) is discarded/used incorrectly.
When I complete the keyword 'while' for example, I get something like:The actual text is provided by clang as optional output. It would be a fairly small change in the code to tell this plugin to ignore clang's suggested output.CodeIs it the clang itself that completes the code like this? Can this behavior be disabled?while(/*! condition !*/){
}
For now I see that the inline Clang warning/error annotations have unconfigurable colours, style number 50. I guess Alpha0010 just chose a number ?I reused the wxsmith generated code entry from the C++ lexer. Eventually it should probably get its own entry, but I did this since that style has the same meaning of "this text is not editable".
I am aware of that but I couldn't locate the piece of code that configures this yet. Can someone point me to the code in question so I can take care of that too?stc->AnnotationSetStyle() (https://github.com/alpha0010/ClangLib/blob/2d64e1d35ed32e1aec5de7ec2c0112d8764d07cb/clangplugin.cpp#L971)
Eventual goal for this plugin was to provide clang powered data that other subsystems (including highlighting, searching, refactoring,...) in addition to CC (hence the plugin name I choose). This will have to be done in a way that data is mediated, so other future plugins can also provide these services.Maybe I should make a merge from this plugin into the CC-plugin, just to make sure the same file is not parsed twice...Nope don't do it. This is something that should be done in the sdk and the cc plugins should only feed it with data.
As far as I know scintilla doesn't have easy way to implement this, so this is why we've not investigated much time.
Yeah, it really is a hack. But if you follow certain coding/naming conventions (similar to C::B core) it *nearly* works without mistakes. I wrote this poor man's semantic highlighting in this technique since it (mostly) runs very fast, and requires no complicated lexer editing.Afaik the built-in cc plugin provides the semantic highlight for the data members currently. I use it and runs quite smooth and nice. I've even enhanced it a little further to color the class names also. I believe it won't hurt to implement this in clang plugin till it's implemented in sdk (which I don't think will ever happen though).The one in the CC is just a hack that breaks in too many ways (it is not context aware, it is just global). :)
Clang
KDevelop always prided itself for its state of the art C++ language support. We introduced innovative code browsing functionality, semantic highlighting and advanced code completion, features that our user base has come to rely upon for their daily work. All of this was made possible by a custom C++ parser, and an extremely complex semantic analyzer for the C++ language. Adding support for all the quirky corner cases in C++, as well as maintaining compatibility with the latest C++ language standards such as C++11, drained our energy and stole time needed to improve other areas of our IDE. Furthermore, the code was so brittle, that it was close to impossible to improve its performance or add bigger new features such as proper C language support.
Now, after close to two years of work, we finally have a solution to this dilemma: A Clang based language plugin. Not only does this give us support for the the very latest C++ language standard, it also enables true C and Objective-C language support. Furthermore, you get all of the immensely useful compiler warnings directly inside your editor. Even better, fixing these warnings is now often just a matter of pressing a single button to apply a Clang provided fix-it!
There are, however, a few caveats that need to be mentioned:
On older machines the performance may be worse than with our legacy C++ support. But the new Clang based plugin finally scales properly with the number of cores on your CPU, which can lead to significantly improved performance on more modern machines.
Some features of our legacy C++ support have not yet been ported to the new plugin. This includes special support for Qt code, most notably signal/slot code completion using the old Qt 4 macro syntax. We will be working on improving this situation and welcome feedback from our users on what we should focus on.
The plugin works fine with Clang 3.6 and above, but some features, such as auto-type resolution in the code browser, or argument code completion hints within a function call, require unreleased extensions to Clang. The required changes have been contributed upstream by members of our community and we intend on continuing this effort. For the best C++ experience in KDevelop, we recommend a custom build of a recent Clang. Alternatively, stay tuned for Clang 3.8 early next year.
CXDiagnostic diag = clang_getDiagnosticInSet(diagSet, i); //i == 0
//ExpandDiagnosticSet(clang_getChildDiagnostics(diag), diagnostics);
size_t numRnges = clang_getDiagnosticNumRanges(diag); //<-- crash here
So this seems to be a use after free inside the plugin. This happens pretty much every time when closing a tab with a header file.Just checked it again, cause the bug's too annoying. This is indeed a use after free, cause clang_getDiagnosticSetFromTU(m_ClTranslUnit); in TranslationUnit::GetDiagnostics is called after clang_disposeTranslationUnit(m_ClTranslUnit); in the TranslationUnit::~TranslationUnit() for the same m_ClTranslUnit, i.e. the TranslationUnit object is reused (by ClangProxy::GetDiagnostics) after its destructor was called as a result of ClangProxy::RemoveTranslationUnit .
So this seems to be a use after free inside the plugin. This happens pretty much every time when closing a tab with a header file.Just checked it again, cause the bug's too annoying. This is indeed a use after free, cause clang_getDiagnosticSetFromTU(m_ClTranslUnit); in TranslationUnit::GetDiagnostics is called after clang_disposeTranslationUnit(m_ClTranslUnit); in the TranslationUnit::~TranslationUnit() for the same m_ClTranslUnit, i.e. the TranslationUnit object is reused (by ClangProxy::GetDiagnostics) after its destructor was called as a result of ClangProxy::RemoveTranslationUnit .
Alpha, yvesdm3000
OK. This was an easy one. Someone just doesn't know, what std::vector::assign is meant for. Btw. I hope those who wrote the copy-constructor of the TranslationUnit as simulating a move-contructor for speed know what they do, cause it might become unsafe.
Patch attached.
As long as it doesn't give me trouble I keep it as-is, it does help to keep the lifetime of the clang TU correct without additional pointers.I think it's rather about avoiding additional copying of the TranslationUnit data. I'm not much into C++, and this was something new to me. It's just important to remember to copy-construct objects from temporary objects only. This includes initialization and assignment as well, because the assignment constructor of TranslationUnit gets the assigned object by value and hence will corrupt it during copy-construction.
yvesdm3000When it's not C++11, the elements in the vector<TranslationUnit> will always be copy-constructed, they will then always be copied again when the vector grows beyond the allocated memory. Now for the clang TU, there is only 1 call to release that memory and when you have multiple copies of that same pointer, doing a clang_releaseTranslationUnit would then be done on all copies and hence freeing the same memory multiple times. Before C++11 we would have solved this with a pointer to TranslationUnit and do memory-management ourselves, with C++11 with the move operator it becomes much easier since the lifetime can be tied to the lifetime of the container elements, and with Alpha's trick of emulating the move operator it seems to perform the same task. It works, so I don't touch it.
I think it's rather about avoiding additional copying of the TranslationUnit data. I'm not much into C++, and this was something new to me. It's just important to remember to copy-construct objects from temporary objects only. This includes initialization and assignment as well, because the assignment constructor of TranslationUnit gets the assigned object by value and hence will corrupt it during copy-construction.
I hope those who wrote the copy-constructor of the TranslationUnit as simulating a move-contructor for speed know what they do, cause it might become unsafe.Casting away a const and editing it is undefined if the original object was created const. However, TranslationUnits must be mutable to interact with clang, so this is not the case. For insurance though, I tried to do the minimum possible operations: 3 pointer copies from the vector swap(), 1 pointer copy for the clang TU.
Regarding RemoveTranslationUnit(), keep in mind that multiple editors for different files may utilize the same TU.
the elements in the vector<TranslationUnit> will always be copy-constructed, they will then always be copied again when the vector grows beyond the allocated memoryYes, and is there a guarantee that they won't be copy-constructed twice from the same object? I mean there is a notion of a sane implementation, but no guarantee, right?
Before C++11 we would have solved this with a pointer to TranslationUnit and do memory-management ourselvesBefore C++11, I think, I would rather implement a simplified version of a shared_ptr . This seems much safer.
Casting away a const and editing it is undefined if the original object was created const.My concerns are rather related to attempts to accidentally do smth. like m_TranslUnits[1] = m_TranslUnits[0]; .
Another problem is that the plugin sometimes gets into an infinite loop inside wxExecute(command, output, errors, wxEXEC_NODISABLE); . Inside the function int wxGUIAppTraits::WaitForChild(wxExecuteData& execData) to be more precise, while GTK_EndProcessDetector is always getting 0 from waitpid and g++ is somehow not present in the process list.OK. I was a bit wrong. The infinite loop in WaitForChild results from the call wxExecute(cmd, output, wxEXEC_NODISABLE);, which is in "sdk / globals.cpp" . The command line is "wx-config --version=2.8 --cflags". It happens on opening a project, but I don't know what conditions it needs. wxconfig started by the call keeps hanging in the process list, endProcData->pid in wxGUIAppTraits::WaitForChild(wxExecuteData& execData) is negative (not sure yet, if it's supposed to be negative) with an absolute value equal to the hanging process. Here's the call stack:
#0 0x7fb2a8045590 wxGUIAppTraits::WaitForChild(wxExecuteData&) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#1 0x7fb2a8045bfb wxExecute(wchar_t**, int, wxProcess*) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#2 0x7fb2a8046345 wxExecute(wxString const&, int, wxProcess*) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#3 0x7fb2a804232b wxDoExecuteWithCapture(wxString const&, wxArrayString&, wxArrayString*, int) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#4 0x7fb2a8a00851 ExpandBackticks(wxString&) (str=...) (globals.cpp:870)
#5 0x7fb2a89a54d5 CompilerCommandGenerator::SetupCompilerOptions(Compiler*, ProjectBuildTarget*) (this=0x59b9e80, compiler=0x2e97240, target=0x59b4000) (compilercommandgenerator.cpp:937)
#6 0x7fb2a89aa3a2 CompilerCommandGenerator::Init(cbProject*) (this=this@entry=0x59b9e80, project=project@entry=0x5982ae0) (compilercommandgenerator.cpp:161)
#7 0x7fb275f511c9 CompilerMINGW::GetCommandGenerator(cbProject*) (this=<optimized out>, project=0x5982ae0) (compilerMINGW.cpp:51)
#8 0x7fb27f2e0ede ClangPlugin::UpdateCompileCommand(cbEditor*) (this=0x23b0b30, ed=0x5a16ca0) (/tmp/l.inc/ClangLib/clangplugin.cpp:995)
#9 0x7fb27f2decaa ClangPlugin::OnEditorActivate(CodeBlocksEvent&) (this=0x23b0b30, event=...) (/tmp/l.inc/ClangLib/clangplugin.cpp:675)
#10 0x7fb27f2f4f5c cbEventFunctor<ClangPlugin, CodeBlocksEvent>::Call(CodeBlocksEvent&) (this=0x2bed0e0, event=...) (/tmp/l.inc/codeblocks-svn/src/include/cbfunctor.h:49)
#11 0x7fb2a8a15930 Manager::ProcessEvent(CodeBlocksEvent&) (this=<optimized out>, event=...) (manager.cpp:263)
#12 0x7fb2a8a22e35 PluginManager::NotifyPlugins(CodeBlocksEvent&) (this=<optimized out>, event=...) (pluginmanager.cpp:1450)
#13 0x7fb2a89e3ba8 EditorManager::SetActiveEditor(EditorBase*) (this=this@entry=0x1ee2d40, ed=0x5a16ca0) (editormanager.cpp:468)
#14 0x7fb2a89e52c3 EditorManager::CheckForExternallyModifiedFiles() (this=0x1ee2d40) (editormanager.cpp:972)
#15 0x7fb2a803e47c wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#16 0x7fb2a803e533 wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#17 0x7fb2a803e8bf wxEvtHandler::ProcessEvent(wxEvent&) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#18 0x7fb2a803e3d8 wxEvtHandler::ProcessPendingEvents() () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#19 0x7fb2a7fb5e69 wxAppConsole::ProcessPendingEvents() () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#20 0x7fb2a80f54ee wxAppBase::ProcessIdle() () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#21 0x7fb2a805f705 wxapp_idle_callback() (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#22 0x7fb2a5c98a8a g_main_context_dispatch() (/lib64/libglib-2.0.so.0:??)
#23 0x7fb2a5c98e20 g_main_context_iterate.isra() (/lib64/libglib-2.0.so.0:??)
#24 0x7fb2a5c98ecc g_main_context_iteration() (/lib64/libglib-2.0.so.0:??)
#25 0x7fb2a7743151 gtk_main_iteration() (/lib64/libgtk-x11-2.0.so.0:??)
#26 0x7fb2a805fc85 wxApp::Yield(bool) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#27 0x7fb2a8045595 wxGUIAppTraits::WaitForChild(wxExecuteData&) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#28 0x7fb2a8045bfb wxExecute(wchar_t**, int, wxProcess*) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#29 0x7fb2a8046345 wxExecute(wxString const&, int, wxProcess*) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
#30 0x7fb2a804232b wxDoExecuteWithCapture(wxString const&, wxArrayString&, wxArrayString*, int) () (/opt/wx/2.8/lib/libwx_gtk2u-2.8.so.0:??)
OK. This was an easy one. [...] Patch attached.No, it wasn't. Now code completion related to the closed file is dead. I'll try to have a look, but I hope one of you guys would fix it, cause it seems I miss many assumptions needed to be considered.
Yeah I understand code completion is probably dead once you have closed (and reopened) a file. That will certainly be fixed with the upcoming push. This push will feature a duplicate TranslationUnit for the current file that is being reparsed, allowing the typing user to use Code Completion while it's being reparsed. It will also parse a TranslationUnit when the clang TU associated with it is missing, such as is the case once you've closed and reopened a file.
No, it wasn't. Now code completion related to the closed file is dead. I'll try to have a look, but I hope one of you guys would fix it, cause it seems I miss many assumptions needed to be considered.
Regarding RemoveTranslationUnit(), keep in mind that multiple editors for different files may utilize the same TU.
For removal, in the short term I'm releasing the TU when the 'main' file that requested the creation of the TU is closed.This is pretty much exactly what my little patch does.
Regarding caching PCH files, is there a good Code::Blocks location where I should place these? Some infrastructure, or is wxStandardPaths::GetTempDir good enough ?Do you really mean precompiled headers, or is it supposed to be a code parser database (like .sdf in Visual Studio)? As for the latter I'd prefer to keep the corresponding information in memory. And you can make an option to store it periodically on disk at a user-defined location. GetTempDir is a good default for such a location.
yvesdm3000QuoteRegarding caching PCH files, is there a good Code::Blocks location where I should place these? Some infrastructure, or is wxStandardPaths::GetTempDir good enough ?Do you really mean precompiled headers, or is it supposed to be a code parser database (like .sdf in Visual Studio)? As for the latter I'd prefer to keep the corresponding information in memory. And you can make an option to store it periodically on disk at a user-defined location. GetTempDir is a good default for such a location.
Btw. how is it going with integrating the plugin into codeblocks-contrib?
Btw. how is it going with integrating the plugin into codeblocks-contrib?This one will land in the core someday. This is not a contrib plugin in.
For codeblocks-contrib, not sure if I am going to do this immediately, I think the plugin needs restructuring first. I want to split the plugin into pieces:If you want to split this in multiple cb plugins, keep in mind that cb gets slower to start the more plugins there are installed (no matter if enabled or disabled).
Btw. how is it going with integrating the plugin into codeblocks-contrib?This one will land in the core someday. This is not a contrib plugin in.For codeblocks-contrib, not sure if I am going to do this immediately, I think the plugin needs restructuring first. I want to split the plugin into pieces:If you want to split this in multiple cb plugins, keep in mind that cb gets slower to start the more plugins there are installed (no matter if enabled or disabled).
Also do you really have added so much code you need to separate it into different pieces?
Obviously we can't assume users will always have enough memory to store that in memory, especially for pretty large projects.Well, I have 16GBs in my work laptop, and I would appreciate an option to not drain my SSD of life with temporary stuff. Besides, you would still need to be able to handle low disk space situations, so why wouldn't you leverage the same out-of-space-avoidance mechanism in memory?
it's better to have ALL files parsed into AST trees. [...] So for example 'goto implementation', it would first look in any TU in memory, if it can't find it, it would go into a slower mode and open each PCH file one by one and see if it can find what it's looking for.Yes, and for the option of no on-disk ASTs it would be necessary to parse all the remaining TUs (a progress bar would make sense), but that's the price for not having enough cache space, no matter if it's on disk or in memory.
yvesdm3000The support I had initially attempted for in plan of this is TokenDatabase (roughly) keeps track (in memory) of where main definitions exist; then if any of those ASTs are not currently loaded, the could be found directly (not implemented), instead of having to re-parse the entire project. The project does need to be parsed once at least, and this index probably should be serialized for searching to be useful between sessions.Quoteit's better to have ALL files parsed into AST trees. [...] So for example 'goto implementation', it would first look in any TU in memory, if it can't find it, it would go into a slower mode and open each PCH file one by one and see if it can find what it's looking for.Yes, and for the option of no on-disk ASTs it would be necessary to parse all the remaining TUs (a progress bar would make sense), but that's the price for not having enough cache space, no matter if it's on disk or in memory.
yvesdm3000QuoteObviously we can't assume users will always have enough memory to store that in memory, especially for pretty large projects.Well, I have 16GBs in my work laptop, and I would appreciate an option to not drain my SSD of life with temporary stuff. Besides, you would still need to be able to handle low disk space situations, so why wouldn't you leverage the same out-of-space-avoidance mechanism in memory?Quoteit's better to have ALL files parsed into AST trees. [...] So for example 'goto implementation', it would first look in any TU in memory, if it can't find it, it would go into a slower mode and open each PCH file one by one and see if it can find what it's looking for.Yes, and for the option of no on-disk ASTs it would be necessary to parse all the remaining TUs (a progress bar would make sense), but that's the price for not having enough cache space, no matter if it's on disk or in memory.
I want something where I do insert them temporarily, but are highlighted with some backgroundcolor and if the user goes to another line, these are removed againThis way the original code will potentially be overwritten, and the fix suggestion might mislead if not appropriate. If you don't make the fix suggestions persistently visible, then I'd prefer a popup as oBFusCATed suggested.
but then I need something visual to actually apply the fixitAs for me a couple of shortcuts would suffice (fix, show another fix, goto next warning/error, goto previous warning/error), but I like when GUI provides multiple ways of doing something, so I would prefer to see these buttons on the ClangCC toolbar as well. Buttons inside of a popup seem to me an overkill.
As for me a couple of shortcuts would suffice
I also think it would be a good idea to have a separate output view that outputs there errors, similar to the build messages.Please don't do this, we have too many logs already, and I'm sure more people won't like the new log pane, then the integrated annotations!
Maybe some people don't like them to be inlined, it would also give a more global overview of the amount of warning/errors.You'll have to find a way to reuse one of the compiler logs or even both. Probably we should move them to the sdk somehow.
All constructive feedback is welcome.I've added a tiny note on commit:
All constructive feedback is welcome.I've added a tiny note on commit:
https://github.com/yvesdm3000/ClangLib/commit/d0d558a1bf5ffe00b3a6dfc4ee816ea6fb48be2a
yvesdm3000
You made a whole bunch of methods public, which rendered the plugin unusable, cause the vector of TUs now works with them as with copyable objects, which results in exceptions (("Illegal copy attempted of TranslationUnit object.")). Btw. the "-ansi" option must be removed, cause it disables many features of C++11.
Another problem is that the plugin works for a single TU only if there are multiple open.
Can you be a little bit more specific?Sorry, I was in a hurry. I do indeed compile the plugin. Precompiled versions of CodeBlocks plugins seem to me only good when being part of a distribution. Otherwise their usefulness scope is too limited.
I even don't test it for C++11 since I want to focus on implementing features first and make the changes for C++11 laterWouldn't you be willing to consider dropping support for C++ older than C++11 at all? C++11 is safer in many ways. E.g. much safer would be to have a vector of unique_ptr's to TUs with enforced move-semantics than having these dirty swap-hacks in a copy-constructor. I see no reason to continue suffering in supporting the older standards. I would even expect the "mysterious crashes" you are talking about in your todo-list to go away after conscientiously switching to C++11.
I remind you this is only a prerelease and by all means not a final product, although I do use it for my daily main job now.I understand that. I was just shocked to see the commented private replaced with public and the private methods being used outside of the class scope. This made me scared about the project becoming a heap of crutches even before the first release would come out.
QuoteI remind you this is only a prerelease and by all means not a final product, although I do use it for my daily main job now.I understand that. I was just shocked to see the commented private replaced with public and the private methods being used outside of the class scope. This made me scared about the project becoming a heap of crutches even before the first release would come out.
For me the plugin does not work with a single TU, it switches TU when the associated document is opened.I was talking about the diagnostics. I've just debugged it a little. And the problem seems to be the GetCurrentTranslationUnitId method, cause it always returns 0. So only the TU that happened to have gotten the m_TranslUnitId == 0 has the diagnostics displayed, which is ensured at the beginning of OnDiagnostics . I removed the if ( m_TranslUnitId == -1 ) condition to always resolve the current TU in GetCurrentTranslationUnitId, and it works OK now.
yvesdm3000You seem to have found a bug there. Thanks for sharing !QuoteFor me the plugin does not work with a single TU, it switches TU when the associated document is opened.I was talking about the diagnostics. I've just debugged it a little. And the problem seems to be the GetCurrentTranslationUnitId method, cause it always returns 0. So only the TU that happened to have gotten the m_TranslUnitId == 0 has the diagnostics displayed, which is ensured at the beginning of OnDiagnostics . I removed the if ( m_TranslUnitId == -1 ) condition to always resolve the current TU in GetCurrentTranslationUnitId, and it works OK now.
Will this clang CC solve the build configuration problem?How should it work? Configure is there to setup the code for your platform and to your needs / options / compilers... So unless you provide magic balls how on earth should any parser know and resolve this?
Most open source projects out there are compiled by the "./configure; make" combo.
And makefiles and configurations can set bazilions preprocessor directives and extra include paths. Can it go through these and still parse correctly?
Manager::Get()->GetLogManager()->DebugLog(F(_("")));
Manager::Get()->GetLogManager()->DebugLogError(F(_("")));
Is it threadsafe ?NO, please see the whole thread discussion here: F() function is not thread safe? (http://forums.codeblocks.org/index.php/topic,18773.msg128612.html#msg128612), also the logger function is not thread safe.
Yves
// remove registered event sinks
Manager::Get()->RemoveAllEventSinksFor(this);
I committed your proposed fix on master. Looks like this was only overlooked in clangdiagnostics.cpp, the other places has the "RemoveAllEventSinksFor(this);".OK, thank you. BTW: There are many more crash candidates. Unfortunately if you use this plugin on Windows it will definitely crash sooner or later. I've never been able to run a complete C::B session w/o crash. :-/
Another thing: Please don't use code that is not portable. alloca for example is very bad and should never be used.A question, where did you see the use of alloca ?
By the way, I would like to help clean up code when I have time.You could also just fork from Yves repo and send pull requests to Yves...
I have done that already. However, since it would likely include a decent number of whitespace edits, I was trying to avoid merging troubles.By the way, I would like to help clean up code when I have time.You could also just fork from Yves repo and send pull requests to Yves...
OK, thank you. BTW: There are many more crash candidates. Unfortunately if you use this plugin on Windows it will definitely crash sooner or later. I've never been able to run a complete C::B session w/o crash. :-/
Another thing: Please don't use code that is not portable. alloca for example is very bad and should never be used. Also, currently your git HEAD is broken because it seems you did commit a file (tokendatabase.cpp) w/o resolving conflicts first.
If possible, I would recommend that you test this plugin from time to time on Windows. Be careful with hacks, they usually don't work on other platforms. If it compiles on Windows, I can help with that from time to time... just guide me what to do.
OK, it certainly looks like you are viewing the 'devel' branch since the alloca and merge-conflict stuff are in there. It should actually be named 'experimental' and contains a lot of hacks and other things that certainly should not be in master (like you pointed out).Ah - ok, that might be my mistake. I though "devel" is where development occurs and master you only use to sync with Alpha. Good to know. So I'll switch to master and try again...
I have some questions:This is to give Clang access to the files that are open in the editor and are not saved, e.g. the changes that are in the buffer of the editor.
1, what are the m_UnsavedFiles means in all the Jobs? (in clangproxy.h file), does every job need such parameter?
2, about SyncJob, you just want to run the task in worker thread, but the mainthread is just blocked, is it possible our ccmanager supply some interface which support synchronized request? I mean if ccmanager ask a code completion list, it just returned, and let a specific cc plugin to do the job to fill something(through synchronized api), and this way, we won't let the main gui thread get blockedSyncJob is mostly 'optionally' synchronous, e.g. the caller can wait for it with a timeout. Initially I didn't understand how the C::B 'GetAutocomplist' worked, it seemed like a synchronous operation to me so I figured I'd start a code-completion and when it took too long, just return empty and be ready for the next request. Later on I saw you can actually do the same code-completion request once the threaded one is finished so I figured I keep the timeout-implementation since it keeps the total operation simple&fast when the clang-operation is faster than 20 milliseconds. So theoretically the 'SyncJob' could be removed from the project again, or at least for the CodeCompleteAtJob.
EDIT: I would suggest you can add some doxygen style document to the source code, so that people(include me) can read and understand or debug the code easily.Sure thing. I'll add it to the top of my todo list for you.
void CCManager::OnEditorHook(cbEditor* ed, wxScintillaEvent& event)
{
wxEventType evtType = event.GetEventType();
if (evtType == wxEVT_SCI_CHARADDED)
{
const wxChar ch = event.GetKey();
// get the char set the active ccplugin is interest to trigger the call tip
CCPluginCharMap::const_iterator ctChars = m_CallTipChars.find(GetProviderFor(ed));
if (ctChars == m_CallTipChars.end())
ctChars = m_CallTipChars.find(nullptr); // default char set
// Are there any characters which could trigger the call tip?
if (ctChars->second.find(ch) != ctChars->second.end())
{
int tooltipMode = Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadInt(wxT("/tooltip_mode"), 1);
if ( tooltipMode != 3 // keybound only
|| m_CallTipActive != wxSCI_INVALID_POSITION )
{
wxCommandEvent pendingShow(cbEVT_DEFERRED_CALLTIP_SHOW);
AddPendingEvent(pendingShow);
}
}
else
{
cbStyledTextCtrl* stc = ed->GetControl();
const int pos = stc->GetCurrentPos();
const int wordStartPos = stc->WordStartPosition(pos, true);
// get the char set the active ccplugin is interest to trigger the suggestion list
CCPluginCharMap::const_iterator alChars = m_AutoLaunchChars.find(GetProviderFor(ed));
if (alChars == m_AutoLaunchChars.end())
alChars = m_AutoLaunchChars.find(nullptr); // default char set
// auto suggest list can be triggered either:
// 1, some number of chars are entered
// 2, an interested char belong to alChars is entered
int autolaunchCt = Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadInt(wxT("/auto_launch_count"), 3);
/* TODO (ollydbg#1#02/22/16): What does the magic number 4 means? */
if ( (pos - wordStartPos >= autolaunchCt && !stc->AutoCompActive())
|| pos - wordStartPos == autolaunchCt + 4 )
{
CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
Manager::Get()->ProcessEvent(evt);
}
else if (alChars->second.find(ch) != alChars->second.end())
{
/* TODO (ollydbg#1#02/22/16): What does the 10 ms used for? Can we just ask plugin to start a code completion session? */
m_AutoLaunchTimer.Start(10, wxTIMER_ONE_SHOT);
m_AutocompPosition = pos; // remember the current caret position
}
}
}
...
On the other hand, I do think the 'GetAutocomplist'-call in the cc-plugin framework looks like an afterthought, something with a request event and a response event would probably have been much nicer, but I'm unaware of the lowlevel choices and scintilla if that would even be possible.I think this is a good method, and we can go with this direction.
@yves:This is not the same timeout. The 20 ms comes after the 10 ms you identified and gives Clang 20 ms to calculate the CC results. If it can do it in 20ms, the code-completion results are returned immediately, otherwise the clang-plugin will post a new code-completion request when the results have arrived.
I think the 20 ms lock time can be removed, at least I see a time delay in the ccmanager, see below:
You can see, there are 10 ms there.
Beware that with the current code-completion support in C::B, it is very complex where a code-completion is requested, handled in a thread, the editor is then modified and then when the operation is finished, the plugin needs to figure out if the code-completion still applies because another code completion might have come in, it might be identical, it might not be, the same request might be pending, and then you do another one in our own callback handler etc... The amount of cases where it can do something else than the user expects is very high.QuoteOn the other hand, I do think the 'GetAutocomplist'-call in the cc-plugin framework looks like an afterthought, something with a request event and a response event would probably have been much nicer, but I'm unaware of the lowlevel choices and scintilla if that would even be possible.I think this is a good method, and we can go with this direction.
You are right, the 20 ms lock is from clangcc, but 10 ms delay is from ccmanager, I mean we do not need the 10ms delay(note that under windows 10ms could be 16ms, because the system time tick), and we just start the clangcc, thus we can save a lot of time.@yves:This is not the same timeout. The 20 ms comes after the 10 ms you identified and gives Clang 20 ms to calculate the CC results. If it can do it in 20ms, the code-completion results are returned immediately, otherwise the clang-plugin will post a new code-completion request when the results have arrived.
I think the 20 ms lock time can be removed, at least I see a time delay in the ccmanager, see below:
You can see, there are 10 ms there.
Oh, and I pushed some doxygen documentation to the 'staging' branch. It's not everything, but it's a start.Great job!
Yves
Beware that with the current code-completion support in C::B, it is very complex where a code-completion is requested, handled in a thread, the editor is then modified and then when the operation is finished, the plugin needs to figure out if the code-completion still applies because another code completion might have come in, it might be identical, it might not be, the same request might be pending, and then you do another one in our own callback handler etc... The amount of cases where it can do something else than the user expects is very high.The current way when code-completion is requested
Nevertheless it's there, in 16.01 so we'll live with it.
Can you show me where that number is? I tried setting a number on the event but that doesn't get used and doesn't come back in the event that is a result of the ccplugin indicating it has some results.Oh, sorry, this is my idea, not implemented yet, I just put there for discussion. Not sure it is good or bad. :)
For what it looks like now, I think I managed to make it work correctly by saving the line/column position where code-completion is requested and when ccplugin is ready, it checks if that position is still valid, if not, drops/cancels the request.Yes, it is also a good choice, if you looked at the GDB's MI interface, it use a number to synchronize a request and a response.
Yves
EDIT: the asynchronized request is just my idea.
An asynchronized request:
1, ccmanager call a function in ccplugin, thus a request is send to ccplugin
2, ccplugin return a special value(maybe a number), and ccmanager know it will return the results later.
3, ccplugin can do the dirty work in a worker thread
4, when result is out, ccplugin can send a message or call a sdk function from ccplugin
5, the result is shown.
If there are another request in between those steps, we can cancel some steps and do it again, a request can have a number, so they don't conflict.
std::vector<cbCodeCompletionPlugin::CCToken> ClangCodeCompletion::GetAutocompList(bool isAuto, cbEditor* ed, int& tknStart, int& tknEnd)
{
// you just use the m_CCOutstandingResults to generate a returned tokens
}
void ClangCodeCompletion::OnCodeCompleteFinished( ClangEvent& event )
{
//CCLogger::Get()->DebugLog( wxT("OnCodeCompleteFinished") );
if ( event.GetTranslationUnitId() != m_TranslUnitId )
{
return;
}
if (m_CCOutstanding > 0)
{
if ( event.GetLocation() != m_CCOutstandingLoc )
{
CCLogger::Get()->DebugLog( wxT("Discard old CodeCompletion request result") );
return;
}
EditorManager* edMgr = Manager::Get()->GetEditorManager();
cbEditor* ed = edMgr->GetBuiltinActiveEditor();
if (ed)
{
m_CCOutstandingResults = event.GetCodeCompletionResults();
if ( m_CCOutstandingResults.size() > 0 )
{
CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
evt.SetInt(1);
Manager::Get()->ProcessEvent(evt);
return;
}
}
m_CCOutstanding--;
}
}
evt.SetInt(1);
virtual std::vector<CCToken> GetAutocompList(bool isAuto, cbEditor* ed, int& tknStart, int& tknEnd) = 0;
A bug report: I think not every source file(cpp or h files) were included in the clanglib.cbp.
A bug report: I think not every source file(cpp or h files) were included in the clanglib.cbp.
use clanglib-unix.cbp or clanglib-msw_64.cbp
Yves
You have to link to the 'codeblocks.dll' in your installation folder. Check the following link for more information:
http://wiki.codeblocks.org/index.php/Linking_the_plugin_to_a_Nightly_Build (http://wiki.codeblocks.org/index.php/Linking_the_plugin_to_a_Nightly_Build)
g++ -DBUILDING_PLUGIN -DNOPCH -Wextra -Wall -std=c++11 -ansi -fPIC -g -I/usr/lib/x86_64-linux-gnu/wx/include/gtk2-unicode-release-2.8 -I/usr/include/wx-2.8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -D__WXGTK__ -pthread -I/usr/lib/llvm-3.6/include -fmessage-length=0 -fexceptions -Winvalid-pch -pthread -I/mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks -I/mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/tinyxml -I/mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/scripting/include -I/mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/scripting/bindings -I/mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/scripting/sqplus -I/mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/wxscintilla/include -DcbDEBUG -I. -c /home/teto/ClangLib/cclogger.cpp -o .objs/plugins/clanglib/cclogger.o
In file included from /mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/sdk_events.h:12:0,
from /mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/manager.h:21,
from /mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/logmanager.h:9,
from /home/teto/ClangLib/cclogger.h:15,
from /home/teto/ClangLib/cclogger.cpp:10:
/mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/prep.h:96:1: warning: identifier ‘nullptr’ is a keyword in C++11 [-Wc++0x-compat]
template<typename T>inline void Delete(T*& p){delete p; p = nullptr;}
^
/mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/prep.h: In function ‘void Delete(T*&)’:
/mnt/ntfs/teto/codeblocks_sf/install/include/codeblocks/prep.h:96:61: error: ‘nullptr’ was not declared in this scope
template<typename T>inline void Delete(T*& p){delete p; p = nullptr;}
No, use nullptr and build in c++11 mode.Hooray :-). I'm looking forward to seeing good use of shared_ptr's, unique_ptr's, compiler-enforced move semantics, etc. and a cleanup from the nasty support of older standards. Some things in the plugin just seemed too counter-natural without C++11.
Since sometime master is using c++11
/home/teto/ClangLib/clangproxy.cpp: In member function ‘void ClangProxy::RemoveTranslationUnit(ClTranslUnitId)’:
/home/teto/ClangLib/clangproxy.cpp:761:33: error: use of deleted function ‘ClTranslationUnit& ClTranslationUnit::operator=(const ClTranslationUnit&)’
m_TranslUnits[translUnitId] = ClTranslationUnit(translUnitId, nullptr);
I however don't want to bypass the original author Alpha about going to C++11 as minimum requirement since he did the original code.I had intended to migrate the code to C++11 once core C::B made the switch. So, green light to go ahead on the change now.
Maybe Alpha can give his point of view on this before I start removing code ?
Thansk for the fix yves, I managed to compile and load it.
I haven't looked at the code yet, do I need to do anything else apart from installing the plugin to enable it (like disabling old CC) ? Any advice on how to stresstest it ?
My project is a custom project, hence the .cbp file does not contain the compilation flags etc... is there a way to pass on a compile_commands.json ?
I was curious to test this plugin compared to YouCompleteMe + Vim which is often not capable of finding the definition. The number of translation unit seems indeed to be the crux of the matter.I used to use YouCompleteMe for a while but it had the same issue that I had with the initial implementation of this plugin: It blocks the UI too often preventing me to type. I will be doing essentially the same thing like they suggest: Parse every file in the project and build a token-to-file relationship. This way the plugin knows which file to parse to go find the implementation.
I was curious how to fix it and I stumbled on this topic that could be of interest to you:
https://github.com/Valloric/ycmd/pull/180
To sum up, clang devs think of providing a standard tool for cross TU interrogation, so maybe you should not spend too much time on this (or do it upstream :p).
What prohibits me to implement this persistence is that the tokendatabase should be linked to a project and not the workspace because you could (theoretically) have 2 separate projects each have a class that share the name but not the implementation.Please keep in mind that it could also be that two targets in a project share the same class with different implementations. there are quite some projects around where that is the case...
If it's something else that I'm not aware of, please specify.I meant that if you say you'll need a token database per projects I say its better per target. Because the very same reason why you don't do it per workspace also applies to projects due to targets.
If it's something else that I'm not aware of, please specify.I meant that if you say you'll need a token database per projects I say its better per target. Because the very same reason why you don't do it per workspace also applies to projects due to targets.
If you can manage that differently somehow I am happy.
typedef union mystruct_t_
{
uint32_t raw;
struct
{
uint32_t offset:12;
uint32_t reserved:24;
} fields;
} mystruct_t;
uint32_t const value =
((mystruct_t) { .fields.reserved = 1 }).raw;
//CC not working here ^
yvesdm3000Hi l_inc,
Hi. I like the plugin a lot, but there are some problems I encountered so far that annoy me (present in this week's staging branch as well):
1) Code completion doesn't work for labels: no matter forward or backward referencedBeside the generic nagging about gotos etc (but I'm also realistic: I should not care about what someone does or even have to do at times!), I fear that the current code-completion support comes completely from the libclang library. I give it the translation unit and a position and the library returns me a list of code-completions where we only filter out constructors and operators when they are not appropriate. Nevertheless I think we should be able to retrieve the labels within the function scope and detect the goto statement and do code-completion ourselves.
2) Code completion doesn't work for fields of unions/structures inside compound literals (in C):It might be libclangs fault, or maybe we are not giving it the correct position. We always go back to the start of the word, that is what libclang wants, but I'm unsure if we do it correctly in this case. I'll try to look at this case later next week.Codetypedef union mystruct_t_
{
uint32_t raw;
struct
{
uint32_t offset:12;
uint32_t reserved:24;
} fields;
} mystruct_t;
uint32_t const value =
((mystruct_t) { .fields.reserved = 1 }).raw;
//CC not working here ^
3) Header files are often parsed incorrectly as main files in their own translation unit. Every file in a project has a property (Properties... -> Build -> Compile file) specifying whether it is a separate translation unit. This property could be a basis for the decision. Besides it would be nice to be able to quickly switch every such header between existing translation units, in which the header file is included, through a quickly accessible menu, because it's not uncommon to have (very) different parsing of the same header depending on the translation unit.Yep, I'm completely aware of this problem. There is some code that should cope with this but it's buggy and disabled. The way I see it is that the currently focussed translation unit will be checked first if it handles the newly focussed header file. This way you could force the 'view' of the header file by going to the header/source file that does some defines before the #include statement and when you would then go to the header file, you'd see it trough that translation unit.
As a side note, unfortunately clang doesn't compile things like static size_t const tmp = "Hello"-"Hello";, which results in a spurious error-diagnostic. But I guess that should rather be reported to the clang developers: even though the standard doesn't guarantee it compiles, it better would as in gcc.That's a drawback of using libclang for code-completion and gcc as a compiler. It would be very hard to fix this since you're mixing up 2 compilers... Best would be to use clang as a compiler too, but often you don't have that option. (Same for me for my other projects. GCC is the only compiler where the product compiles, nevertheless I find clangcc very usefull for code-completion.
Beside the generic nagging about gotos etc (but I'm also realistic: I should not care about what someone does or even have to do at times!)I'm very fastidious with respect to coding style, and I always try to find the cleanest and clearest way of doing things. Starting to use goto's was (once) a result of a critical analysis of my C code. While I totally support most of the critics of goto, there's one single case where it does a better job in supporting clean and clear code in C than anything else. And that's error handling. Especially when you handle resource allocation errors while allocating three or more resources in a function. That's a generally accepted application of goto's and the only one I make use of in my code. In C++ RAII is in many cases a better alternative, but we don't have that in C.
Nevertheless I think we should be able to retrieve the labels within the function scope and detect the goto statement and do code-completion ourselves.Well, thank you for considering that option. However I expected libclang to be somewhat more clever in that respect. If it doesn't support code completion for labels, then I'd first bugreport that to the libclang developers.
I'll try to look at this case later next week.OK. Thanks for taking your time looking into that.
This way you could force the 'view' of the header file by going to the header/source file that does some defines before the #include statement and when you would then go to the header file, you'd see it trough that translation unit.I see this kind of implementation as a possible temporary workaround. But a drop-down or a quick popup with an assignable hotkey (like the one you have on Ctrl+Tab) seems to me more user-friendly.
GCC is the only compiler where the product compiles, nevertheless I find clangcc very usefull for code-completionTotally. And in general you're right regarding the issues of using different compilers. However clang developers target broad compatibility with gcc, and I'm gonna find some time to report at least this little issue to the clang developers, as supporting string merging in this specific case is arguably better than not supporting, even though this goes beyond the requirements imposed by the C standard.
yvesdm3000It looks like I've been doing too much C++ the last 2 years. I actually agree about using goto's and resources in C. It's not an ideal solution but there is no other clean alternative. Some do the for( ; ; ) and break thing but I find it cluttering and misuse of the for loop. I've also seen some code that have defines to hide that for-loop trick, but had side-effects on its own, especially around the warnings/errors it emits when doing something wrong.
I'm very fastidious with respect to coding style, and I always try to find the cleanest and clearest way of doing things. Starting to use goto's was (once) a result of a critical analysis of my C code. While I totally support most of the critics of goto, there's one single case where it does a better job in supporting clean and clear code in C than anything else. And that's error handling. Especially when you handle resource allocation errors while allocating three or more resources in a function. That's a generally accepted application of goto's and the only one I make use of in my code. In C++ RAII is in many cases a better alternative, but we don't have that in C.
Well, thank you for considering that option. However I expected libclang to be somewhat more clever in that respect. If it doesn't support code completion for labels, then I'd first bugreport that to the libclang developers.I'll try to file a bugreport for this.
I see this kind of implementation as a possible temporary workaround. But a drop-down or a quick popup with an assignable hotkey (like the one you have on Ctrl+Tab) seems to me more user-friendly.I'm not sure about the details on what you propose in the sub-menu. I guess it should have a list of filenames (e.g. the top-parent of the translation unit) to select under which context you wish to view the header file?
Some do the for( ; ; ) and break thing but I find it cluttering and misuse of the for loopYes, that's using a more complicated mechanism to simulate a better fitting primitive one. This consideration also allows to view a do { /*...*/ } while(0); construct as a more appropriate replacement, although still ugly. I actually preferred nesting of the if (/*...*/) {/*...*/} construct. But in all cases that only stops further proceeding and therefore is only half of the story. The second half is to deallocate the resources, which needs more clutter of constructs. I used a switch with all fall-through cases:
NTSTATUS HighlyNestedFun()
{
NTSTATUS ntStatus = STATUS_SUCCESS;
enum failure_stage {success, res1_failure, res2_failure, res3_failure, res4_failure, res5_failure}
failureStage = success;
HANDLE hRes1, hRes2, hRes3, hRes4, hRes5;
hRes1 = AcquireResource1();
if (!hRes1)
ntStatus = STATUS_INSUFFICIENT_RESOURCES1, failureStage = res1_failure;
else
{
hRes2 = AcquireResource2();
if (!hRes2)
ntStatus = STATUS_INSUFFICIENT_RESOURCES2, failureStage = res2_failure;
else
{
hRes3 = AcquireResource3();
if (!hRes3)
ntStatus = STATUS_INSUFFICIENT_RESOURCES3, failureStage = res3_failure;
else
{
hRes4 = AcquireResource4();
if (!hRes4)
ntStatus = STATUS_INSUFFICIENT_RESOURCES4, failureStage = res4_failure;
else
{
hRes5 = AcquireResource5();
if (!hRes5)
ntStatus = STATUS_INSUFFICIENT_RESOURCES5, failureStage = res5_failure;
else
{
//using acquired resources
}
}
}
}
}
switch (failureStage)
{
case success:
FreeResource5(hRes5);
case res5_failure:
FreeResource4(hRes4);
case res4_failure:
FreeResource3(hRes3);
case res3_failure:
FreeResource2(hRes2);
case res2_failure:
FreeResource1(hRes1);
case res1_failure:
}
return ntStatus;
}
I guess it should have a list of filenames (e.g. the top-parent of the translation unit) to select under which context you wish to view the header file?Yes. In contrast to your idea to switch back and forth between the file and possible roots of the corresponding translation units this also allows to cover some convoluted cases, in which the same file within the same project serves both as a root of a translation unit as well as an included file.
You can always post bugs and feature requests hereThank you. I have to think about creating an account on github first. :-)
Yes I briefly looked at that and tried enabling it againWhat exactly do you enable?
The problem is that reparsing doesn't work correctly in that setup.If I understand the problem correctly, it should be possible to make clang create the PCH cache for an include subtree of an include tree of a particular selectable translation unit. Meaning that you view the header file as a root of a virtual include tree that is terminated at the point of first inclusion of the header file in the original tree of the chosen translation unit. Essentially this way of parsing is a generalization of your current parsing for the case when the virtual include tree does not match the actual include tree that is built starting directly from the header file as the root.
yvesdm3000There is some lookup code where given a specific FileId it searches for an existing translation unit. This is currently disabledQuoteYes I briefly looked at that and tried enabling it againWhat exactly do you enable?
<-- Really needed to read this a couple of times... The PCH cache creation is completely handled by Clang and is simply enabled by an option flag. Maybe we should find a way to handle this PCH cache ourselves?QuoteThe problem is that reparsing doesn't work correctly in that setup.If I understand the problem correctly, it should be possible to make clang create the PCH cache for an include subtree of an include tree of a particular selectable translation unit. Meaning that you view the header file as a root of a virtual include tree that is terminated at the point of first inclusion of the header file in the original tree of the chosen translation unit. Essentially this way of parsing is a generalization of your current parsing for the case when the virtual include tree does not match the actual include tree that is built starting directly from the header file as the root.
<-- Really needed to read this a couple of times... The PCH cache creation is completely handled by Clang and is simply enabled by an option flag.I'm sorry for unclear expressions. I must have given an example of what interface I expect libclang to provide to achieve this. Ideally I expect libclang to allow to setup a callback. This callback should be called every time libclang processes the include directive. And the callback should allow to stop PCH generation. The resulting PCH then represents the result of processing of the subtree I was talking about. In case such a callback interface is not provided, it shouldn't be too complicated to add such an interface.
honestly: your project files (for windows) are a danger for the commonality. Everywhere hard coded paths (THE OUTPUT IS TO C:\git ????????? honestly??????) ...Hi,
i have cleaned up and will make a pull request, but i am not able to run the plugin... Codeblocks gives me errors about symbols not loaded and depwalker shows me unresolved symbols for libclang.dll i thought clang is linked in statically?
[edit:] my problem is that the official build of clang is for msvc and i need a build for mingw...
How does this plugin gather and feed the files and flags to clang?
Can it use a compiler database?
I guess you are need the compilation flags to come out of the compiler_commands.json that is generated from ninja ?Yes, the cb project generated by cmake doesn't contain flags (it is custom makefile based project), so the cc will have very hard time gathering them.
My main job's project is also using a custom makefile. I simply mirror the compiler options enough so that ClangCC is working fine. To change options, i switch from custom makefile to cb, set an option and then toggle the custom makefile option back to 'on'. I'm not sure this is a bug in cb to be able to query the compile options when the custom makefile option is on but it sure is handy for me.I guess you are need the compilation flags to come out of the compiler_commands.json that is generated from ninja ?Yes, the cb project generated by cmake doesn't contain flags (it is custom makefile based project), so the cc will have very hard time gathering them.
Probably we can add a field in the project with the path of the compilation database and then the CC could use it.
We can also teach other tools and plugins to use it.
I guess you are need the compilation flags to come out of the compiler_commands.json that is generated from ninja ?Yes, the cb project generated by cmake doesn't contain flags (it is custom makefile based project), so the cc will have very hard time gathering them.
Probably we can add a field in the project with the path of the compilation database and then the CC could use it.
We can also teach other tools and plugins to use it.
ClangLib: translUnitId == wxNOT_FOUND, cannot complete in file \codeblocks_sf\src\sdk\cbplugin.cpp
Any reason why you added a new target? Can't we just update the existing targets?With this target you can't run it trough the run button. But it creates a "install able" file you can distribute. The other targets let you to run codeblocks with the plugin installed there? I did want to modify this targets, because modifying them would may be break your workflow?
1) The name of the binary is somehow unlucky... ClangLib sounds as it is something from clang but not a code completion plugin. I think ccClang or something like this would be acb_clang_complete or something in this style is event better name.
I probably could have done a better job choosing the name; I had not considered "lib" being in important prefix/suffix...
The intent of the name was that this plugin would also support other functionality retrievable via clang, such as true semantic highlighting, auto suggest (+/- apply) fixes for warnings and errors, refactoring, reformatting, etc.
Another note: if you're using CC_LOCKER_TRACK_TT_MTX_LOCK I guess you'll have to fix its implementation ;)We should totally remove those lockers. :)
codeblocks.exe caused an Access Violation at location 4309DC03 Reading from location 4309DC03.
Registers:
eax=4309dc03 ebx=00000001 ecx=28c0e370 edx=28c0e370 esi=0028bad4 edi=00000000
eip=4309dc03 esp=0028ba50 ebp=0028baec iopl=0 nv up ei pl nz ac po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210216
AddrPC Params
4309DC03 00000001 00000001 00000001
0A92A530 28C0E370 0028BA94 0028BB30 clanglib.dll!BeginHighlightOccurrences [cclang-plugin/src/ClangLib/src/clangrefactoring.cpp @ 227]
225: ClTokenPosition loc(line + 1, pos - stc->PositionFromLine(line) + 1);
226:
> 227: m_pClangPlugin->RequestOccurrencesOf( translId, ed->GetFilename(), loc );
228: }
229:
0A92A171 0028BC4C 02EFD728 0028BC7C clanglib.dll!OnTimer [cclang-plugin/src/ClangLib/src/clangrefactoring.cpp @ 181]
179:
180: if (evId == idHighlightTimer)
> 181: BeginHighlightOccurrences(ed);
182: else
183: event.Skip();
Another note: if you're using CC_LOCKER_TRACK_TT_MTX_LOCK I guess you'll have to fix its implementation ;)That's a file that I grabbed as-is from the regular CC plugin? I guess it has been updated there too?
Dear Yves,
I've tried to compile this plugin on a more recent compiler. I suggest to apply the patch that is attached to:
- get rid of the deprecated auto_ptr
- simplify the singleton pattern
- fix an compiler error in non-PCH builds due to missing #include <iostream>
The patch applies to 2 files on the staging branch only: cclogger{.h/.cpp}.
AddrPC Params
02FEABF6 0000002E FFFFFFFF 0028BAD4 wxmsw28u_gcc_custom.dll!wxStringBase::rfind
02FED382 0000002E 00000001 0028BB64 wxmsw28u_gcc_custom.dll!wxString::Find
02FED3DB 2F772C98 0000002E 0028E488 wxmsw28u_gcc_custom.dll!wxString::AfterLast
618734B6 2F772C98 00000001 00000000 codeblocks.dll!FileTypeOf
0BA78572 2D171550 0E8AA3B0 2B0D5A50 compiler.dll!SetupIncludeDirs [codeblocks_sf/src/plugins/compilergcc/compilerMINGWgenerator.cpp @ 55]
53: {
54: ProjectFile* f = *it;
> 55: if (FileTypeOf(f->relativeFilename) == ftHeader &&
56: f->compile)
57: {
6181B4CA 2AA20288 0A84315C 00000024 codeblocks.dll!CompilerCommandGenerator::Init
0BA75442 2AA20288 0028E488 00000000 compiler.dll!GetCommandGenerator [codeblocks_sf/src/plugins/compilergcc/compilerMINGW.cpp @ 51]
49: {
50: CompilerMINGWGenerator *generator = new CompilerMINGWGenerator;
> 51: generator->Init(project);
52: return generator;
53: }
0A756A6E 063E0198 2F789598 2D29D1C8 clanglib.dll!GetCompileCommand [ClangLib/src/clangplugin.cpp @ 1186]
1184: if (compileCommandStr.IsEmpty())
1185: compileCommandStr = wxT("$options $includes");
> 1186: CompilerCommandGenerator* gen = comp->GetCommandGenerator(proj);
1187: if (gen)
1188: gen->GenerateCommandLine(compileCommandStr, target, pf, filename,
0A757958 2D29D070 FFFFFFFC 0028C484 clanglib.dll!UpdateCompileCommand [ClangLib/src/clangplugin.cpp @ 1262]
1260: int ClangPlugin::UpdateCompileCommand(cbEditor* ed)
1261: {
> 1262: std::vector<wxString> compileCommand = GetCompileCommand( ed->GetProjectFile(), ed->GetFilename() );
1263:
1264: if (compileCommand.empty())
0A753B54 0028C518 0028C484 0028C3D4 clanglib.dll!OnEditorActivate [ClangLib/src/clangplugin.cpp @ 656]
654: if(m_TranslUnitId == wxNOT_FOUND)
655: m_TranslUnitId = GetTranslationUnitId(filename);
> 656: UpdateCompileCommand(ed);
657: if (m_TranslUnitId == wxNOT_FOUND)
658: {
0A7B008F 0028C518 0028C418 06332D18 clanglib.dll!Call [wxWidgets-2.8.12/include/wx/buffer.h @ 127]
125: #endif // wxABI_VERSION >= 20804
126:
> 127: DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
128: #if wxABI_VERSION >= 20804
129: DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
6188D58E 0028C518 FFFFFFFC 0028C454 codeblocks.dll!Manager::ProcessEvent
618A321B 0028C518 FFFFFFFF 00000000 codeblocks.dll!PluginManager::NotifyPlugins
61856F4D 0028D044 2D3508C8 0028C5D4 codeblocks.dll!EditorManager::OnPageChanged
02FA1261 06331094 61856DBA FFFFFFFC wxmsw28u_gcc_custom.dll!wxAppConsole::HandleEvent
0302436E 61C32430 06331094 0028D044 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEventIfMatches
0302443A 0028D044 06331094 030243E3 wxmsw28u_gcc_custom.dll!wxEventHashTable::HandleEvent
03024895 0028D044 06332D1C 030243E3 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 16 times ---
03024829 0028D044 0028C828 030243E3 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
0A751716 0028D044 06585ED0 0028C954 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
03024829 0028D044 0641E648 525A6C97 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 54 times ---
03024829 0028D044 00000000 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028D044 05DFD9A8 0323C913 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
03024829 0028D044 000000B3 033B31D5 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
03247331 0000002B 0028D0C4 0028D0C8 wxmsw28u_gcc_custom.dll!wxAuiNotebook::SetSelection
03247B2A 0000001E 0028D168 033B9FCC wxmsw28u_gcc_custom.dll!wxAuiNotebook::RemovePage
03247BC3 0000001E 2D3508C8 0028D1E0 wxmsw28u_gcc_custom.dll!wxAuiNotebook::DeletePage
617C7E84 0000001E 00000003 2CC706A4 codeblocks.dll!cbAuiNotebook::DeletePage
618531BA 2D3508C8 00000001 0028D1C4 codeblocks.dll!EditorManager::Close
61853140 0028D22C 00000001 0028D224 codeblocks.dll!EditorManager::Close
617F27E4 00000001 00000000 00000000 codeblocks.dll!cbProject::CloseAllFiles
618C1F53 2AA20288 00000000 00000001 codeblocks.dll!ProjectManager::CloseProject
0049091E 0028DF84 0000000D 0000001A codeblocks.exe!ProjectManagerUI::OnCloseProject
02FA1261 05ECBAE8 004906FC 00000000 wxmsw28u_gcc_custom.dll!wxAppConsole::HandleEvent
0302436E 00590460 05ECBAE8 0028DF84 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEventIfMatches
0302443A 0028DF84 05ECBAE8 0028D4E4 wxmsw28u_gcc_custom.dll!wxEventHashTable::HandleEvent
03024895 0028DF84 05E18F48 0028D504 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 16 times ---
03024829 0028DF84 00000000 0028D724 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
0A751716 0028DF84 06585ED0 00000040 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
03024829 0028DF84 0641E648 0028D784 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 53 times ---
03024829 0028DF84 00000000 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028DF84 062EDBD8 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
03024829 0028DF84 04102D6C 2F7B7CB0 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028DF84 00000366 00000084 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
0310DA81 00000366 00000000 00000000 wxmsw28u_gcc_custom.dll!wxMenuBase::SendEvent
0309A32B 00000000 00000366 00000000 wxmsw28u_gcc_custom.dll!wxMenu::MSWCommand
0306DAB0 00000366 00000000 00000000 wxmsw28u_gcc_custom.dll!wxWindow::HandleCommand
0307134C 00000111 00000366 00000000 wxmsw28u_gcc_custom.dll!wxWindow::MSWWindowProc
030BF047 00000111 00000366 00000000 wxmsw28u_gcc_custom.dll!wxTreeCtrl::MSWWindowProc
0306ADAE 00040AA8 00000111 00000366 wxmsw28u_gcc_custom.dll!wxWndProc
770E62FA 0306AD60 00040AA8 00000111 USER32.dll!_InternalCallWinProc@20
770E6D3A 00000000 0306AD60 00040AA8 USER32.dll!_UserCallWinProcCheckWow@32
770E77C4 0306AD60 00000000 0028E588 USER32.dll!_DispatchMessageWorker@8
770E788A 0028E554 00000000 00000111 USER32.dll!_DispatchMessageW@4
0306FBB9 0028E664 0000007E 00000066 wxmsw28u_gcc_custom.dll!wxWindow::DoPopupMenu
004F7C06 0028E664 0028E8B8 0028E800 codeblocks.exe!wxWindowBase::PopupMenu
0048AC05 2E0A2378 0028E8B8 00770020 codeblocks.exe!ProjectManagerUI::ShowMenu
0048DB76 0028F468 00000000 00000000 codeblocks.exe!ProjectManagerUI::OnTreeItemRightClick
02FA1261 05ECBAE8 0048DAD2 00000000 wxmsw28u_gcc_custom.dll!wxAppConsole::HandleEvent
0302436E 00590178 05ECBAE8 0028F468 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEventIfMatches
0302443A 0028F468 05ECBAE8 00000000 wxmsw28u_gcc_custom.dll!wxEventHashTable::HandleEvent
03024895 0028F468 05E18F48 00000000 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 16 times ---
03024829 0028F468 00000000 00000000 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
0A751716 0028F468 06585ED0 2FD76F80 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
03024829 0028F468 0641E648 6DBFBC4E wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
---- repeats 54 times -----
03024829 0028F468 00000000 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028F468 062EDBD8 0028F3B8 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
03024829 0028F468 770E965E 00000014 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028F468 00001111 00000000 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
030BDF15 00000361 0028F968 0028F618 wxmsw28u_gcc_custom.dll!wxTreeCtrl::MSWOnNotify
0307240C 0000004E 00000361 0028F968 wxmsw28u_gcc_custom.dll!wxWindow::MSWWindowProc
0306ADAE 00090BAE 0000004E 00000361 wxmsw28u_gcc_custom.dll!wxWndProc
770E62FA 0306AD60 00090BAE 0000004E USER32.dll!_InternalCallWinProc@20
770E6D3A 00000000 0306AD60 00090BAE USER32.dll!_UserCallWinProcCheckWow@32
770E965E 04512E20 00000000 0306AD60 USER32.dll!_SendMessageWorker@24
770E96C5 00090BAE 0000004E 00000361 USER32.dll!_SendMessageW@16
030BFBE4 00000204 00000002 0066007E wxmsw28u_gcc_custom.dll!wxTreeCtrl::MSWWindowProc
0306ADAE 00040AA8 00000204 00000002 wxmsw28u_gcc_custom.dll!wxWndProc
770E62FA 0306AD60 00040AA8 00000204 USER32.dll!_InternalCallWinProc@20
770E6D3A 00000000 0306AD60 00040AA8 USER32.dll!_UserCallWinProcCheckWow@32
770E77C4 0306AD60 00000000 0028FBE8 USER32.dll!_DispatchMessageWorker@8
770E788A 0028FBC4 00000000 00000000 USER32.dll!_DispatchMessageW@4
0304FAEF 2A7D0B58 00000001 0028FD40 wxmsw28u_gcc_custom.dll!wxEventLoop::Dispatch
> 55: if (FileTypeOf(f->relativeFilename) == ftHeader &&I would also verify "f"not being NULL:
77B9E49B 2B27A350 0ABEF9C0 0FBA7650 ntdll.dll!0x2e49b
77B9E0A3 040C0000 00000000 2B27A350 ntdll.dll!_RtlFreeHeap@12
754C98CD 2B27A350 2B27A350 0004F980 msvcrt.dll!_free
033C793D 2DDE13EC 034FDDAC FFFFFFFF wxmsw28u_gcc_custom.dll!wxWCharBuffer::~wxWCharBuffer
0A3039BF 0ABEF928 2DDE13EC 7FCE500D clanglib.dll!FromUTF8 [wxWidgets-2.8.12/include/wx/buffer.h @ 127]
125: #endif // wxABI_VERSION >= 20804
126:
> 127: DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
128: #if wxABI_VERSION >= 20804
129: DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
0A2C834E 2EA192D8 0ABEFA2C 00000001 clanglib.dll!UpdateIncludeDiagnosticsVisitor [ClangLib/src/translationunit.cpp @ 630]
628:
629: str = clang_getFileName(included_file);
> 630: wxString includedFileName = wxString::FromUTF8(clang_getCString(str));
631: clang_disposeString(str);
632: if (data->errorIncludes.find( includedFileName ) != data->errorIncludes.end())
> 55: if (FileTypeOf(f->relativeFilename) == ftHeader &&I would also verify "f"not being NULL:
if (f && FileTypeOf(f->relativeFilename) == ftHeader &&
...especially on shut-down.
And an other crash report:Code77B9E49B 2B27A350 0ABEF9C0 0FBA7650 ntdll.dll!0x2e49b
77B9E0A3 040C0000 00000000 2B27A350 ntdll.dll!_RtlFreeHeap@12
754C98CD 2B27A350 2B27A350 0004F980 msvcrt.dll!_free
033C793D 2DDE13EC 034FDDAC FFFFFFFF wxmsw28u_gcc_custom.dll!wxWCharBuffer::~wxWCharBuffer
0A3039BF 0ABEF928 2DDE13EC 7FCE500D clanglib.dll!FromUTF8 [wxWidgets-2.8.12/include/wx/buffer.h @ 127]
125: #endif // wxABI_VERSION >= 20804
126:
> 127: DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
128: #if wxABI_VERSION >= 20804
129: DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
0A2C834E 2EA192D8 0ABEFA2C 00000001 clanglib.dll!UpdateIncludeDiagnosticsVisitor [ClangLib/src/translationunit.cpp @ 630]
628:
629: str = clang_getFileName(included_file);
> 630: wxString includedFileName = wxString::FromUTF8(clang_getCString(str));
631: clang_disposeString(str);
632: if (data->errorIncludes.find( includedFileName ) != data->errorIncludes.end())
It's probably better if I switch to std::string for anything that crosses these threads and force c++11 to assure thread-safety. I'll make a POC and see if that improves reliability.wxString in wxWidgets 2.8.12 is not thread safe, and it should be thread safe in wxWidgets 3.0+, because it use std::string, and std::string is atomic reference counted. There is same issue in the native CC, and it's hard to solve unless we move to wx3.0+.
77B9E0A3 040C0000 00000000 2B27A350 ntdll.dll!_RtlFreeHeap@12
754C98CD 2B27A350 2B27A350 0004F980 msvcrt.dll!_free
033C793D 2DDE13EC 034FDDAC FFFFFFFF wxmsw28u_gcc_custom.dll!wxWCharBuffer::~wxWCharBuffer
0A3039BF 0ABEF928 2DDE13EC 7FCE500D clanglib.dll!FromUTF8 [wxWidgets-2.8.12/include/wx/buffer.h @ 127]
125: #endif // wxABI_VERSION >= 20804
126:
> 127: DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
128: #if wxABI_VERSION >= 20804
129: DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
0A2C834E 2EA192D8 0ABEFA2C 00000001 clanglib.dll!UpdateIncludeDiagnosticsVisitor [ClangLib/src/translationunit.cpp @ 630]
628:
629: str = clang_getFileName(included_file);
> 630: wxString includedFileName = wxString::FromUTF8(clang_getCString(str));
631: clang_disposeString(str);
632: if (data->errorIncludes.find( includedFileName ) != data->errorIncludes.end())
wxString::FromUTF8(clang_getCString(str))
wxString clang_to_wxString(clangstring* str)
{
if(str == nullptr)
return wxEmptyString;
else
return wxString::FromUTF8(clang_getCString(str));
}
Quote from: MortenMacFly on 27-02-2017, 07:06:00with the bt:
Quote from: BlueHazzard on 27-02-2017, 01:17:55
> 55: if (FileTypeOf(f->relativeFilename) == ftHeader &&
I would also verify "f"not being NULL:
if (f && FileTypeOf(f->relativeFilename) == ftHeader &&
...especially on shut-down.
Sorry this is in compiler.dll and not in the clanglib plugin.
AddrPC Params
02FEABF6 0000002E FFFFFFFF 0028BAD4 wxmsw28u_gcc_custom.dll!wxStringBase::rfind
02FED382 0000002E 00000001 0028BB64 wxmsw28u_gcc_custom.dll!wxString::Find
02FED3DB 2F772C98 0000002E 0028E488 wxmsw28u_gcc_custom.dll!wxString::AfterLast
618734B6 2F772C98 00000001 00000000 codeblocks.dll!FileTypeOf
0BA78572 2D171550 0E8AA3B0 2B0D5A50 compiler.dll!SetupIncludeDirs [codeblocks_sf/src/plugins/compilergcc/compilerMINGWgenerator.cpp @ 55]
53: {
54: ProjectFile* f = *it;
> 55: if (FileTypeOf(f->relativeFilename) == ftHeader &&
56: f->compile)
57: {
6181B4CA 2AA20288 0A84315C 00000024 codeblocks.dll!CompilerCommandGenerator::Init
0BA75442 2AA20288 0028E488 00000000 compiler.dll!GetCommandGenerator [codeblocks_sf/src/plugins/compilergcc/compilerMINGW.cpp @ 51]
49: {
50: CompilerMINGWGenerator *generator = new CompilerMINGWGenerator;
> 51: generator->Init(project);
52: return generator;
53: }
0A756A6E 063E0198 2F789598 2D29D1C8 clanglib.dll!GetCompileCommand [ClangLib/src/clangplugin.cpp @ 1186]
1184: if (compileCommandStr.IsEmpty())
1185: compileCommandStr = wxT("$options $includes");
> 1186: CompilerCommandGenerator* gen = comp->GetCommandGenerator(proj);
1187: if (gen)
1188: gen->GenerateCommandLine(compileCommandStr, target, pf, filename,
0A757958 2D29D070 FFFFFFFC 0028C484 clanglib.dll!UpdateCompileCommand [ClangLib/src/clangplugin.cpp @ 1262]
1260: int ClangPlugin::UpdateCompileCommand(cbEditor* ed)
1261: {
> 1262: std::vector<wxString> compileCommand = GetCompileCommand( ed->GetProjectFile(), ed->GetFilename() );
1263:
1264: if (compileCommand.empty())
0A753B54 0028C518 0028C484 0028C3D4 clanglib.dll!OnEditorActivate [ClangLib/src/clangplugin.cpp @ 656]
654: if(m_TranslUnitId == wxNOT_FOUND)
655: m_TranslUnitId = GetTranslationUnitId(filename);
> 656: UpdateCompileCommand(ed);
657: if (m_TranslUnitId == wxNOT_FOUND)
658: {
0A7B008F 0028C518 0028C418 06332D18 clanglib.dll!Call [wxWidgets-2.8.12/include/wx/buffer.h @ 127]
125: #endif // wxABI_VERSION >= 20804
126:
> 127: DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
128: #if wxABI_VERSION >= 20804
129: DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
6188D58E 0028C518 FFFFFFFC 0028C454 codeblocks.dll!Manager::ProcessEvent
618A321B 0028C518 FFFFFFFF 00000000 codeblocks.dll!PluginManager::NotifyPlugins
61856F4D 0028D044 2D3508C8 0028C5D4 codeblocks.dll!EditorManager::OnPageChanged
02FA1261 06331094 61856DBA FFFFFFFC wxmsw28u_gcc_custom.dll!wxAppConsole::HandleEvent
0302436E 61C32430 06331094 0028D044 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEventIfMatches
0302443A 0028D044 06331094 030243E3 wxmsw28u_gcc_custom.dll!wxEventHashTable::HandleEvent
03024895 0028D044 06332D1C 030243E3 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 16 times ---
03024829 0028D044 0028C828 030243E3 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
0A751716 0028D044 06585ED0 0028C954 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
03024829 0028D044 0641E648 525A6C97 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 54 times ---
03024829 0028D044 00000000 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028D044 05DFD9A8 0323C913 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
03024829 0028D044 000000B3 033B31D5 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
03247331 0000002B 0028D0C4 0028D0C8 wxmsw28u_gcc_custom.dll!wxAuiNotebook::SetSelection
03247B2A 0000001E 0028D168 033B9FCC wxmsw28u_gcc_custom.dll!wxAuiNotebook::RemovePage
03247BC3 0000001E 2D3508C8 0028D1E0 wxmsw28u_gcc_custom.dll!wxAuiNotebook::DeletePage
617C7E84 0000001E 00000003 2CC706A4 codeblocks.dll!cbAuiNotebook::DeletePage
618531BA 2D3508C8 00000001 0028D1C4 codeblocks.dll!EditorManager::Close
61853140 0028D22C 00000001 0028D224 codeblocks.dll!EditorManager::Close
617F27E4 00000001 00000000 00000000 codeblocks.dll!cbProject::CloseAllFiles
618C1F53 2AA20288 00000000 00000001 codeblocks.dll!ProjectManager::CloseProject
0049091E 0028DF84 0000000D 0000001A codeblocks.exe!ProjectManagerUI::OnCloseProject
02FA1261 05ECBAE8 004906FC 00000000 wxmsw28u_gcc_custom.dll!wxAppConsole::HandleEvent
0302436E 00590460 05ECBAE8 0028DF84 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEventIfMatches
0302443A 0028DF84 05ECBAE8 0028D4E4 wxmsw28u_gcc_custom.dll!wxEventHashTable::HandleEvent
03024895 0028DF84 05E18F48 0028D504 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 16 times ---
03024829 0028DF84 00000000 0028D724 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
0A751716 0028DF84 06585ED0 00000040 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
03024829 0028DF84 0641E648 0028D784 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 53 times ---
03024829 0028DF84 00000000 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028DF84 062EDBD8 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
03024829 0028DF84 04102D6C 2F7B7CB0 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028DF84 00000366 00000084 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
0310DA81 00000366 00000000 00000000 wxmsw28u_gcc_custom.dll!wxMenuBase::SendEvent
0309A32B 00000000 00000366 00000000 wxmsw28u_gcc_custom.dll!wxMenu::MSWCommand
0306DAB0 00000366 00000000 00000000 wxmsw28u_gcc_custom.dll!wxWindow::HandleCommand
0307134C 00000111 00000366 00000000 wxmsw28u_gcc_custom.dll!wxWindow::MSWWindowProc
030BF047 00000111 00000366 00000000 wxmsw28u_gcc_custom.dll!wxTreeCtrl::MSWWindowProc
0306ADAE 00040AA8 00000111 00000366 wxmsw28u_gcc_custom.dll!wxWndProc
770E62FA 0306AD60 00040AA8 00000111 USER32.dll!_InternalCallWinProc@20
770E6D3A 00000000 0306AD60 00040AA8 USER32.dll!_UserCallWinProcCheckWow@32
770E77C4 0306AD60 00000000 0028E588 USER32.dll!_DispatchMessageWorker@8
770E788A 0028E554 00000000 00000111 USER32.dll!_DispatchMessageW@4
0306FBB9 0028E664 0000007E 00000066 wxmsw28u_gcc_custom.dll!wxWindow::DoPopupMenu
004F7C06 0028E664 0028E8B8 0028E800 codeblocks.exe!wxWindowBase::PopupMenu
0048AC05 2E0A2378 0028E8B8 00770020 codeblocks.exe!ProjectManagerUI::ShowMenu
0048DB76 0028F468 00000000 00000000 codeblocks.exe!ProjectManagerUI::OnTreeItemRightClick
02FA1261 05ECBAE8 0048DAD2 00000000 wxmsw28u_gcc_custom.dll!wxAppConsole::HandleEvent
0302436E 00590178 05ECBAE8 0028F468 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEventIfMatches
0302443A 0028F468 05ECBAE8 00000000 wxmsw28u_gcc_custom.dll!wxEventHashTable::HandleEvent
03024895 0028F468 05E18F48 00000000 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 16 times ---
03024829 0028F468 00000000 00000000 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
0A751716 0028F468 06585ED0 2FD76F80 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
03024829 0028F468 0641E648 6DBFBC4E wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
---- repeats 54 times -----
03024829 0028F468 00000000 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028F468 062EDBD8 0028F3B8 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
03024829 0028F468 770E965E 00000014 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028F468 00001111 00000000 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
030BDF15 00000361 0028F968 0028F618 wxmsw28u_gcc_custom.dll!wxTreeCtrl::MSWOnNotify
0307240C 0000004E 00000361 0028F968 wxmsw28u_gcc_custom.dll!wxWindow::MSWWindowProc
0306ADAE 00090BAE 0000004E 00000361 wxmsw28u_gcc_custom.dll!wxWndProc
770E62FA 0306AD60 00090BAE 0000004E USER32.dll!_InternalCallWinProc@20
770E6D3A 00000000 0306AD60 00090BAE USER32.dll!_UserCallWinProcCheckWow@32
770E965E 04512E20 00000000 0306AD60 USER32.dll!_SendMessageWorker@24
770E96C5 00090BAE 0000004E 00000361 USER32.dll!_SendMessageW@16
030BFBE4 00000204 00000002 0066007E wxmsw28u_gcc_custom.dll!wxTreeCtrl::MSWWindowProc
0306ADAE 00040AA8 00000204 00000002 wxmsw28u_gcc_custom.dll!wxWndProc
770E62FA 0306AD60 00040AA8 00000204 USER32.dll!_InternalCallWinProc@20
770E6D3A 00000000 0306AD60 00040AA8 USER32.dll!_UserCallWinProcCheckWow@32
770E77C4 0306AD60 00000000 0028FBE8 USER32.dll!_DispatchMessageWorker@8
770E788A 0028FBC4 00000000 00000000 USER32.dll!_DispatchMessageW@4
0304FAEF 2A7D0B58 00000001 0028FD40 wxmsw28u_gcc_custom.dll!wxEventLoop::Dispatch
0A751716 0028F468 06585ED0 2FD76F80 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
Yes, Prove of Concept, I adapt some operations that are used in the project load&unload scenario that I was using and see if this specific problem is fixed.It's probably better if I switch to std::string for anything that crosses these threads and force c++11 to assure thread-safety. I'll make a POC and see if that improves reliability.wxString in wxWidgets 2.8.12 is not thread safe, and it should be thread safe in wxWidgets 3.0+, because it use std::string, and std::string is atomic reference counted. There is same issue in the native CC, and it's hard to solve unless we move to wx3.0+.
What does POC mean? Prove of Concept?
A other problem i noted quite frequently is if you open a new cpp file, enter code at the end of the file (no line text after the last line code) and this code has errors, so they get reported by the instant error reporting wxScilite will report some error about writing past the buffer, or writing non printable characters or something like this. I am actively investigating in this if i find some time.Sounds familiar, I fixed something similar in the past, but it was only reproducible on Windows. Sadly I don't test it often on Windows. It's hard enough as it is to test on wx28, wx30, ubuntu, centos, ...
This is no crash, but a assert()
I don't recall how i can reproduce this, but i will report as soon i am able to reproduce it...
regarding this crash:QuoteQuote from: MortenMacFly on 27-02-2017, 07:06:00with the bt:
Quote from: BlueHazzard on 27-02-2017, 01:17:55
> 55: if (FileTypeOf(f->relativeFilename) == ftHeader &&
I would also verify "f"not being NULL:
if (f && FileTypeOf(f->relativeFilename) == ftHeader &&
...especially on shut-down.
Sorry this is in compiler.dll and not in the clanglib plugin.CodeAddrPC Params
02FEABF6 0000002E FFFFFFFF 0028BAD4 wxmsw28u_gcc_custom.dll!wxStringBase::rfind
02FED382 0000002E 00000001 0028BB64 wxmsw28u_gcc_custom.dll!wxString::Find
02FED3DB 2F772C98 0000002E 0028E488 wxmsw28u_gcc_custom.dll!wxString::AfterLast
618734B6 2F772C98 00000001 00000000 codeblocks.dll!FileTypeOf
0BA78572 2D171550 0E8AA3B0 2B0D5A50 compiler.dll!SetupIncludeDirs [codeblocks_sf/src/plugins/compilergcc/compilerMINGWgenerator.cpp @ 55]
53: {
54: ProjectFile* f = *it;
> 55: if (FileTypeOf(f->relativeFilename) == ftHeader &&
56: f->compile)
57: {
6181B4CA 2AA20288 0A84315C 00000024 codeblocks.dll!CompilerCommandGenerator::Init
0BA75442 2AA20288 0028E488 00000000 compiler.dll!GetCommandGenerator [codeblocks_sf/src/plugins/compilergcc/compilerMINGW.cpp @ 51]
49: {
50: CompilerMINGWGenerator *generator = new CompilerMINGWGenerator;
> 51: generator->Init(project);
52: return generator;
53: }
0A756A6E 063E0198 2F789598 2D29D1C8 clanglib.dll!GetCompileCommand [ClangLib/src/clangplugin.cpp @ 1186]
1184: if (compileCommandStr.IsEmpty())
1185: compileCommandStr = wxT("$options $includes");
> 1186: CompilerCommandGenerator* gen = comp->GetCommandGenerator(proj);
1187: if (gen)
1188: gen->GenerateCommandLine(compileCommandStr, target, pf, filename,
0A757958 2D29D070 FFFFFFFC 0028C484 clanglib.dll!UpdateCompileCommand [ClangLib/src/clangplugin.cpp @ 1262]
1260: int ClangPlugin::UpdateCompileCommand(cbEditor* ed)
1261: {
> 1262: std::vector<wxString> compileCommand = GetCompileCommand( ed->GetProjectFile(), ed->GetFilename() );
1263:
1264: if (compileCommand.empty())
0A753B54 0028C518 0028C484 0028C3D4 clanglib.dll!OnEditorActivate [ClangLib/src/clangplugin.cpp @ 656]
654: if(m_TranslUnitId == wxNOT_FOUND)
655: m_TranslUnitId = GetTranslationUnitId(filename);
> 656: UpdateCompileCommand(ed);
657: if (m_TranslUnitId == wxNOT_FOUND)
658: {
0A7B008F 0028C518 0028C418 06332D18 clanglib.dll!Call [wxWidgets-2.8.12/include/wx/buffer.h @ 127]
125: #endif // wxABI_VERSION >= 20804
126:
> 127: DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
128: #if wxABI_VERSION >= 20804
129: DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
6188D58E 0028C518 FFFFFFFC 0028C454 codeblocks.dll!Manager::ProcessEvent
618A321B 0028C518 FFFFFFFF 00000000 codeblocks.dll!PluginManager::NotifyPlugins
61856F4D 0028D044 2D3508C8 0028C5D4 codeblocks.dll!EditorManager::OnPageChanged
02FA1261 06331094 61856DBA FFFFFFFC wxmsw28u_gcc_custom.dll!wxAppConsole::HandleEvent
0302436E 61C32430 06331094 0028D044 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEventIfMatches
0302443A 0028D044 06331094 030243E3 wxmsw28u_gcc_custom.dll!wxEventHashTable::HandleEvent
03024895 0028D044 06332D1C 030243E3 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 16 times ---
03024829 0028D044 0028C828 030243E3 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
0A751716 0028D044 06585ED0 0028C954 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
03024829 0028D044 0641E648 525A6C97 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 54 times ---
03024829 0028D044 00000000 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028D044 05DFD9A8 0323C913 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
03024829 0028D044 000000B3 033B31D5 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
03247331 0000002B 0028D0C4 0028D0C8 wxmsw28u_gcc_custom.dll!wxAuiNotebook::SetSelection
03247B2A 0000001E 0028D168 033B9FCC wxmsw28u_gcc_custom.dll!wxAuiNotebook::RemovePage
03247BC3 0000001E 2D3508C8 0028D1E0 wxmsw28u_gcc_custom.dll!wxAuiNotebook::DeletePage
617C7E84 0000001E 00000003 2CC706A4 codeblocks.dll!cbAuiNotebook::DeletePage
618531BA 2D3508C8 00000001 0028D1C4 codeblocks.dll!EditorManager::Close
61853140 0028D22C 00000001 0028D224 codeblocks.dll!EditorManager::Close
617F27E4 00000001 00000000 00000000 codeblocks.dll!cbProject::CloseAllFiles
618C1F53 2AA20288 00000000 00000001 codeblocks.dll!ProjectManager::CloseProject
0049091E 0028DF84 0000000D 0000001A codeblocks.exe!ProjectManagerUI::OnCloseProject
02FA1261 05ECBAE8 004906FC 00000000 wxmsw28u_gcc_custom.dll!wxAppConsole::HandleEvent
0302436E 00590460 05ECBAE8 0028DF84 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEventIfMatches
0302443A 0028DF84 05ECBAE8 0028D4E4 wxmsw28u_gcc_custom.dll!wxEventHashTable::HandleEvent
03024895 0028DF84 05E18F48 0028D504 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 16 times ---
03024829 0028DF84 00000000 0028D724 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
0A751716 0028DF84 06585ED0 00000040 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
03024829 0028DF84 0641E648 0028D784 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 53 times ---
03024829 0028DF84 00000000 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028DF84 062EDBD8 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
03024829 0028DF84 04102D6C 2F7B7CB0 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028DF84 00000366 00000084 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
0310DA81 00000366 00000000 00000000 wxmsw28u_gcc_custom.dll!wxMenuBase::SendEvent
0309A32B 00000000 00000366 00000000 wxmsw28u_gcc_custom.dll!wxMenu::MSWCommand
0306DAB0 00000366 00000000 00000000 wxmsw28u_gcc_custom.dll!wxWindow::HandleCommand
0307134C 00000111 00000366 00000000 wxmsw28u_gcc_custom.dll!wxWindow::MSWWindowProc
030BF047 00000111 00000366 00000000 wxmsw28u_gcc_custom.dll!wxTreeCtrl::MSWWindowProc
0306ADAE 00040AA8 00000111 00000366 wxmsw28u_gcc_custom.dll!wxWndProc
770E62FA 0306AD60 00040AA8 00000111 USER32.dll!_InternalCallWinProc@20
770E6D3A 00000000 0306AD60 00040AA8 USER32.dll!_UserCallWinProcCheckWow@32
770E77C4 0306AD60 00000000 0028E588 USER32.dll!_DispatchMessageWorker@8
770E788A 0028E554 00000000 00000111 USER32.dll!_DispatchMessageW@4
0306FBB9 0028E664 0000007E 00000066 wxmsw28u_gcc_custom.dll!wxWindow::DoPopupMenu
004F7C06 0028E664 0028E8B8 0028E800 codeblocks.exe!wxWindowBase::PopupMenu
0048AC05 2E0A2378 0028E8B8 00770020 codeblocks.exe!ProjectManagerUI::ShowMenu
0048DB76 0028F468 00000000 00000000 codeblocks.exe!ProjectManagerUI::OnTreeItemRightClick
02FA1261 05ECBAE8 0048DAD2 00000000 wxmsw28u_gcc_custom.dll!wxAppConsole::HandleEvent
0302436E 00590178 05ECBAE8 0028F468 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEventIfMatches
0302443A 0028F468 05ECBAE8 00000000 wxmsw28u_gcc_custom.dll!wxEventHashTable::HandleEvent
03024895 0028F468 05E18F48 00000000 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
--- repeats 16 times ---
03024829 0028F468 00000000 00000000 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
0A751716 0028F468 06585ED0 2FD76F80 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
03024829 0028F468 0641E648 6DBFBC4E wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
---- repeats 54 times -----
03024829 0028F468 00000000 FEEDBAB1 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028F468 062EDBD8 0028F3B8 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
03024829 0028F468 770E965E 00000014 wxmsw28u_gcc_custom.dll!wxEvtHandler::ProcessEvent
031338F2 0028F468 00001111 00000000 wxmsw28u_gcc_custom.dll!wxWindowBase::TryParent
030BDF15 00000361 0028F968 0028F618 wxmsw28u_gcc_custom.dll!wxTreeCtrl::MSWOnNotify
0307240C 0000004E 00000361 0028F968 wxmsw28u_gcc_custom.dll!wxWindow::MSWWindowProc
0306ADAE 00090BAE 0000004E 00000361 wxmsw28u_gcc_custom.dll!wxWndProc
770E62FA 0306AD60 00090BAE 0000004E USER32.dll!_InternalCallWinProc@20
770E6D3A 00000000 0306AD60 00090BAE USER32.dll!_UserCallWinProcCheckWow@32
770E965E 04512E20 00000000 0306AD60 USER32.dll!_SendMessageWorker@24
770E96C5 00090BAE 0000004E 00000361 USER32.dll!_SendMessageW@16
030BFBE4 00000204 00000002 0066007E wxmsw28u_gcc_custom.dll!wxTreeCtrl::MSWWindowProc
0306ADAE 00040AA8 00000204 00000002 wxmsw28u_gcc_custom.dll!wxWndProc
770E62FA 0306AD60 00040AA8 00000204 USER32.dll!_InternalCallWinProc@20
770E6D3A 00000000 0306AD60 00040AA8 USER32.dll!_UserCallWinProcCheckWow@32
770E77C4 0306AD60 00000000 0028FBE8 USER32.dll!_DispatchMessageWorker@8
770E788A 0028FBC4 00000000 00000000 USER32.dll!_DispatchMessageW@4
0304FAEF 2A7D0B58 00000001 0028FD40 wxmsw28u_gcc_custom.dll!wxEventLoop::Dispatch
you will note that this is a stack overflow crash.And the stack is nearly 210 calls in the clang library.Actually it is in the event handling code of wx 210 calls. So i think there is somewhere a recursive event loop.So this is a clang problem.
I am not this familiar with the event system so i didn't looked over it to much...This is underlined by this messages from the btI think this is a clang problem because of this returning bt information:Code[Edit:] correcting the hypothesis0A751716 0028F468 06585ED0 2FD76F80 clanglib.dll!ProcessEvent [ClangLib/src/clangplugin.cpp @ 222]
220: bool ClangPlugin::ProcessEvent( wxEvent& event )
221: {
> 222: if (cbPlugin::ProcessEvent(event))
223: return true;
224: for (std::vector<ClangPluginComponent*>::iterator it = m_ActiveComponentList.begin(); it != m_ActiveComponentList.end(); ++it)
Normally I try to keep these wxString objects created&destroyed on the same thread or deep-copied if they need to be handed over from one thread to another. It's probably better if I switch to std::string for anything that crosses these threads and force c++11 to assure thread-safety.How are you doing the deep-copies? I'm thinking of adding something like cbDeepCopyWxString that is reliable for both wx2.8 and wx3.0.
A other problem i noted quite frequently is if you open a new cpp file, enter code at the end of the file (no line text after the last line code) and this code has errors, so they get reported by the instant error reporting wxScilite will report some error about writing past the buffer, or writing non printable characters or something like this. I am actively investigating in this if i find some time.Sounds familiar, I fixed something similar in the past, but it was only reproducible on Windows. Sadly I don't test it often on Windows. It's hard enough as it is to test on wx28, wx30, ubuntu, centos, ...
This is no crash, but a assert()
I don't recall how i can reproduce this, but i will report as soon i am able to reproduce it...
Yves
diff --git a/src/clangrefactoring.cpp b/src/clangrefactoring.cpp
index b3913ac..f88b76d 100644
--- a/src/clangrefactoring.cpp
+++ b/src/clangrefactoring.cpp
@@ -217,8 +217,8 @@ void ClangRefactoring::BeginHighlightOccurrences(cbEditor* ed)
// Set Styling:
// clear all style indications set in a previous run (is also done once after text gets unselected)
stc->IndicatorClearRange(0, stc->GetLength());
-
- if (stc->GetTextRange(pos - 1, pos + 1).Strip().IsEmpty())
+ int max_length = std::min(pos + 1 ,stc->GetLength());
+ if (stc->GetTextRange(pos - 1, max_length).Strip().IsEmpty())
return;
const int line = stc->LineFromPosition(pos);
Normally I try to keep these wxString objects created&destroyed on the same thread or deep-copied if they need to be handed over from one thread to another. It's probably better if I switch to std::string for anything that crosses these threads and force c++11 to assure thread-safety.How are you doing the deep-copies? I'm thinking of adding something like cbDeepCopyWxString that is reliable for both wx2.8 and wx3.0.
Also switching to std::string is not really a good idea - you'll do many conversions and possibly loose unicode support (you'll have to use wstring for that).
A other problem i noted quite frequently is if you open a new cpp file, enter code at the end of the file (no line text after the last line code) and this code has errors, so they get reported by the instant error reporting wxScilite will report some error about writing past the buffer, or writing non printable characters or something like this. I am actively investigating in this if i find some time.Sounds familiar, I fixed something similar in the past, but it was only reproducible on Windows. Sadly I don't test it often on Windows. It's hard enough as it is to test on wx28, wx30, ubuntu, centos, ...
This is no crash, but a assert()
I don't recall how i can reproduce this, but i will report as soon i am able to reproduce it...
Yves
This seems to fix the error:Codei honestly don't know if it changes the behavior of the function, but at least it does not give this annoying message ;) . The decision if this is the right fix i let for the developer...diff --git a/src/clangrefactoring.cpp b/src/clangrefactoring.cpp
index b3913ac..f88b76d 100644
--- a/src/clangrefactoring.cpp
+++ b/src/clangrefactoring.cpp
@@ -217,8 +217,8 @@ void ClangRefactoring::BeginHighlightOccurrences(cbEditor* ed)
// Set Styling:
// clear all style indications set in a previous run (is also done once after text gets unselected)
stc->IndicatorClearRange(0, stc->GetLength());
-
- if (stc->GetTextRange(pos - 1, pos + 1).Strip().IsEmpty())
+ int max_length = std::min(pos + 1 ,stc->GetLength());
+ if (stc->GetTextRange(pos - 1, max_length).Strip().IsEmpty())
return;
const int line = stc->LineFromPosition(pos);
Normally I try to keep these wxString objects created&destroyed on the same thread or deep-copied if they need to be handed over from one thread to another. It's probably better if I switch to std::string for anything that crosses these threads and force c++11 to assure thread-safety.How are you doing the deep-copies? I'm thinking of adding something like cbDeepCopyWxString that is reliable for both wx2.8 and wx3.0.
Also switching to std::string is not really a good idea - you'll do many conversions and possibly loose unicode support (you'll have to use wstring for that).
In wx3.0 in most implementations (gcc until 5.x) the string is still reference counted, but it is protected by an atomic. So deep copying is useful there, too.If I remember correctly, if the wxString(std::string) is atomic reference counted, it is theadsafe. I mean the wxCommandEvent should be threadsafe. What's what the atomic reference counter used for, in "copy on write" mode.
Also in wx3.0 they've added a clone method: http://docs.wxwidgets.org/3.1.0/classwx_string.html#afe63f53ecaa197333c405ca985f733fe wxString::Clone.
ASSERT INFO:
/usr/include/wx-3.0/wx/datetime.h(876): assert "IsValid() && dt.IsValid()" failed in operator!=(): invalid wxDateTime
BACKTRACE:
[1] ClangToolbar::OnEditorHook(cbEditor*, wxScintillaEvent&)
[2] EditorHooks::CallHooks(cbEditor*, wxScintillaEvent&)
[3] cbEditor::OnScintillaEvent(wxScintillaEvent&)
[4] cbEditor::OnEditorUpdateUI(wxScintillaEvent&)
[5] wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const
[6] wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&)
[7] wxEvtHandler::SearchDynamicEventTable(wxEvent&)
[8] wxEvtHandler::TryHereOnly(wxEvent&)
[9] wxEvtHandler::ProcessEventLocally(wxEvent&)
[10] wxEvtHandler::ProcessEvent(wxEvent&)
[11] wxWindowBase::TryAfter(wxEvent&)
[12] wxScintilla::NotifyParent(SCNotification*)
[13] ScintillaWX::NotifyParent(SCNotification)
[14] Editor::NotifyUpdateUI()
[15] Editor::Paint(Surface*, PRectangle)
[16] ScintillaWX::DoPaint(wxDC*, wxRect)
[17] wxScintilla::OnPaint(wxPaintEvent&)
[18] wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const
[19] wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&)
[20] wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*)
[21] wxEvtHandler::TryHereOnly(wxEvent&)
[22] wxEvtHandler::DoTryChain(wxEvent&)
[23] wxEvtHandler::ProcessEvent(wxEvent&)
[24] wxEvtHandler::SafelyProcessEvent(wxEvent&)
[25] wxWindow::GTKSendPaintEvents(_GdkRegion const*)
[26] g_closure_invoke
[27] g_signal_emit_valist
[28] g_signal_emit
[29] gtk_main_do_event
[30] gdk_window_process_all_updates
[31] g_main_context_dispatch
[32] g_main_context_iteration
[33] gtk_main_iteration
[34] wxWindow::DoPopupMenu(wxMenu*, int, int)
[35] wxWindowBase::PopupMenu(wxMenu*, int, int)
[36] wxWindowBase::PopupMenu(wxMenu*, wxPoint const&) /usr/include/wx-3.0/wx/window.h:1216
[37] EditorBase::DisplayContextMenu(wxPoint const&, ModuleType)
[38] cbStyledTextCtrl::OnContextMenu(wxContextMenuEvent&)
[39] wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const
[40] wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&)
[41] wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*)
[42] wxEvtHandler::TryHereOnly(wxEvent&)
[43] wxEvtHandler::DoTryChain(wxEvent&)
[44] wxEvtHandler::ProcessEvent(wxEvent&)
[45] wxEvtHandler::SafelyProcessEvent(wxEvent&)
[46] g_closure_invoke
[47] g_signal_emit_valist
[48] g_signal_emit
[49] gtk_propagate_event
[50] gtk_main_do_event
[51] g_main_context_dispatch
[52] g_main_loop_run
[53] gtk_main
[54] wxGUIEventLoop::DoRun()
[55] wxEventLoopBase::Run()
[56] wxAppConsoleBase::MainLoop()
[57] CodeBlocksApp::OnRun() codeblocks_sf/src/src/app.cpp:850
[58] wxEntry(int&, wchar_t**)
[59] CodeBlocks codeblocks_sf/src/src/app.cpp:322
[60] __libc_start_main
[61] _start
if ( (ed->GetLastModificationTime() != m_CurrentState.m_CurrentEditorModificationTime)||(m_Function&&(m_Function->GetCount()==0)))
Reindex on tokenindexdb 0x3831db0 project=codeblocks_sf/src/CodeBlocks_wx30-unix.cbp /codeblocks_sf/src/include/configurationpanel.h
ClTranslationUnit::Parse id=127
[Thread 0x7fffb6732700 (LWP 20185) exited]
ClTranslationUnit::UpdateTokenDatabase 127 finished: 74779 tokens processed
How is the update algorithm of the cc? If i open the codeblocks project file one of my processors is at 100% and the console outputsCodeReindex on tokenindexdb 0x3831db0 project=codeblocks_sf/src/CodeBlocks_wx30-unix.cbp /codeblocks_sf/src/include/configurationpanel.h
ClTranslationUnit::Parse id=127
[Thread 0x7fffb6732700 (LWP 20185) exited]
ClTranslationUnit::UpdateTokenDatabase 127 finished: 74779 tokens processed
could this be a recursive loop?
Does the parser indexes all files all the time, or does it stop after all project files are parsed?
thank you for your work!
greetings
#0 0xa6ed440 __cxa_throw() ( output\share\codeblocks\plugins\clanglib.dll:??)
#1 0xa6ec266 operator new(unsigned int) () ( output\share\codeblocks\plugins\clanglib.dll:??)
#2 0xa7bae18 typeinfo for std::time_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >() ( output\share\codeblocks\plugins\clanglib.dll:??)
#3 0xa6f0200 std::bad_alloc::what() const() ( output\share\codeblocks\plugins\clanglib.dll:??)
#4 0xa7784c9 std::allocator_traits<std::allocator<ClAbstractToken> >::max_size(__a=...) (mingw32/4.9.2/include/c++/bits/alloc_traits.h:422)
#5 0xa7784a8 std::allocator_traits<std::allocator<ClAbstractToken> >::allocate(__a=..., __n=131072) (mingw32/4.9.2/include/c++/bits/alloc_traits.h:357)
#6 0xa762a99 std::_Vector_base<ClAbstractToken, std::allocator<ClAbstractToken> >::_M_allocate(this=0x55a1d0bc, __n=131072) ( mingw32/4.9.2/include/c++/bits/stl_vector.h:170)
#7 0xa786642 std::vector<ClAbstractToken, std::allocator<ClAbstractToken> >::_M_emplace_back_aux<ClAbstractToken const&>(this=0x55a1d0bc) ( mingw32/4.9.2/include/c++/bits/vector.tcc:412)
#8 0xa786a06 std::vector<ClAbstractToken, std::allocator<ClAbstractToken> >::push_back(this=0x55a1d0bc, __x=...) ( mingw32/4.9.2/include/c++/bits/stl_vector.h:923)
#9 0xa723c8c ClTreeMap<ClAbstractToken>::Insert(this=0x55a1d0b8, key=..., value=...) ( cclang-plugin/src/ClangLib/src/treemap.h:37)
#10 0xa6e3c77 ClTokenDatabase::InsertToken(this=0xb00fdc8, token=...) ( cclang-plugin\src\ClangLib\src\tokendatabase.cpp:960)
#11 0xa6e9bf0 ClImportClangToken(cursor=..., scopeCursor=..., typ=ClTokenType_FuncDecl, client_data=0xb00fcc8) ( cclang-plugin\src\ClangLib\src\translationunit.cpp:886)
#12 0xa6ea1ea ClAST_Visitor(cursor=..., parent=..., client_data=0xb00fcc8) ( cclang-plugin\src\ClangLib\src\translationunit.cpp:983)
#13 0xf212b76 libclang!clang_disposeTranslationUnit() ( output\libclang.dll:??)
#14 0x42f42028 ?? () (??:??)
#15 0xf215041 libclang!clang_isTranslationUnit() ( output\libclang.dll:??)
#16 0x8 ?? () (??:??)
#17 ?? ?? () (??:??)