libclang and plugins

Hi,

i am working on a plugin for clang that will show me some custom diagnostics.

I extended the “Hello World”-plugin PrintFunctionNames so that it emits an errors if it finds a function declaration ( its just a toy plugin )
Everything works fine if i execute it from command line with clang.

Hi,

i am working on a plugin for clang that will show me some custom diagnostics.

I extended the “Hello World”-plugin PrintFunctionNames so that it emits an errors if it finds a function declaration ( its just a toy plugin )
Everything works fine if i execute it from command line with clang.


$ clang -Xclang -load -Xclang /PrintFunctionNames.so -Xclang -add-plugin -Xclang print-fns main.cpp

top-level-decl: “foo”
/home/incubus/test/clang-plugins/main.cpp:3:1: error: use of undeclared identifier ‘foo’
void foo()
^
/home/incubus/test/clang-plugins/main.cpp:12:5: error: use of undeclared identifier ‘bar’
bar();
^
top-level-decl: “main”
/home/incubus/test/clang-plugins/main.cpp:8:1: error: use of undeclared identifier ‘main’
int main(int argc, char** argv){
^
3 errors generated.


the first and third error are from my plugin and the second is from clang itself.

Now i want to do the same thing through libclang.
I am using the vim plugin YouCompleteMe to send all of the flags that were passed to clang, to libclang.

I followed the path of execution to
clang_parseTranslationUnit → clang_parseTranslationUnit2 → clang_parseTranslationUnit_impl →
ASTUnit::LoadFromCommandLine → ASTUnit::LoadFromCompilerInvocation → ASTUnit::Parse

were the parsing process is started.

in FrontendAction::BeginSourceFile the method FrontendAction::CreateWrappedASTConsumer is called which creates ASTConsumers from the plugins.
I found out that the Consumer is not created because the FrontendPluginRegistry does not contain any plugins.
This is due to the fact that the plugin was never loaded.

I searched the codebase for the loading routines and found out that the only loading is in clang::ExecuteCompilerInvocation.
I know that clang_parseTranslationUnit is supposed to Parse the translation unit not to execute the whole compiler.

My question is:

Is there any way to load the plugin earlier so that it can be executed while parsing?
Or if it is not possible. Is there some other way to add custom error messages that will be emitted when running clang_parseTranslationUnit?

I think the right solution is to add a way to load plugins when running with libclang.
I see 2 options:

  1. add a call to libclang to allow loading of plugins
  • less complexity in the driver
  • libclang tools need to get explicit support for this
  1. make the driver allow loading clang plugins
  • “just works” with any editor integration
  • more complexity in the driver

I’m leaning towards (2). If you want to give implementing it a try, I’d be happy to review patches…

Cheers,
/Manuel

ok i did something that makes it work, but i don’t know whether its a good way to do it.
It works when the plugin is called from clang and libclang.
I even see my errors appear in vim through YouCompleteMe.

First i added a method loadPlugins() in CompilerInstance that simply does what it was doing before in ExecuteCompilerInvocation.
In ExecuteCompilerIncovation i removed the loading and called the new method.
I did the same thing in ASTUnit::Parse.
The problem is, that libclang does not export all the needed symbols that are needed for plugins to link against it when loaded.
So i added the symbols to tools/libclang/libclang.exports.
Additionally i added a dependency to the plugin so that it links against libclang.
I think this is not the way it should be done.
What would be a better way to do this ?

https://gist.github.com/realincubus/6cba9934b0d49f539446

Greetings Stefan Kemnitz

Send the patch to cfe-commits and we can loop in all the right people to review it / chime in there, I think.
Generally it sounds like what you did makes sense, but I’m not sure what the trade-offs are in various areas here…