[cfe-dev] Source to source transformations questions in branches/tooling
klimek at google.com
Mon Jun 25 00:28:42 PDT 2012
On Sun, Jun 24, 2012 at 4:53 PM, Philip Dunstan <phil at philipdunstan.com>wrote:
> I've been trying some source to source transformations using the
> matcher/callback framework in the tooling branch. They are mostly working
> but I have a couple of questions and would like some feedback on whether I
> am doing everything as intended. Will you please help me?
> There are two transformations I am trying to make: adding the override
> keyword to virtual functions where we can and replacing shared_ptr by
> value function parameters with const references. I have attached the two
> cpp files to this post. They are also available from
> Adds the override specifier to functions that override virtual
> functions from a base class and don't already have the override specifier.
> I have written the following matcher to find candidates functions.
> AST_MATCHER(clang::CXXMethodDecl, IsOverrideMissing)
> // does this virtual function override a virtual function from
> a base class
> return (Node.isVirtual() && (Node.size_overridden_methods() >
> 0) && !Node.hasAttr<OverrideAttr>());
> In my callback however I don't know how to find the right source location
> to insert the override keyword. If there is no body I can use the end of
> the function declaration. However if there is a body I don't know how to
> get the end of the declaration section before the body. For example in the
> following example I want to insert the keyword before the comment. How do I
> get the source location of this point?
> void f() const // overrides a base class virtual function
I'll leave answering that to Daniel.
> Replace function parameters that specify a shared_ptr instance by
> value with shared_ptr by const reference.
> Should I be changing the type from shared_ptr<X> to const shared_ptr<X>& or
> is there a way to do this by modifying the AST to make the parameter const
> and by reference and then re-emit the source?
If you can match the location of the shared_ptr and the type, you can emit
a replacement to "const X&" (no need to go through the AST here). Is there
a part of the matching that's problematic?
> I have this working for normal functions, methods and template functions
> where instantiations of that template exist. What type of matcher should I
> write to match a template function that doesn't have an instantiation.
> eg template <typename T> f(shared_ptr<T>);
Ugh. Templates that are never instantiated anywhere are really hard to
handle, as in your example all the types are dependent. -ast-dump-xml and
friends also don't really help here. I'll put it on my list to write a tool
that helps answer that kind of question.
> Additional Questions:
> It appears that I need to specify all of the system c++ include files when
> I run the tool on a file, but I don't need to provide them when I compile
> the with the clang compiler that I have built from the tooling branch. Is
> this expected behavior?
> replace-shared_ptr-parameters input.cpp -- -std=c++11 -Wall -g -O0
> -I/usr/include/c++/4.6 -I/usr/include/c++/4.6/x86_64-linux-gnu
> -I/usr/include/c++/4.6/backward -I/usr/lib/gcc/x86_64-linux-gnu/4.6/include
> -I/usr/local/include -I/usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed
> -I/usr/include/x86_64-linux-gnu -I/usr/include
Hm, this should work in principle. Can you add '-v' output to both the tool
run and the clang run from your self-built clang compiler and attach them?
A different solution would be to use the CompilationDatabase. If your
project uses cmake, it works out of the box; if not, the easiest thing is
to create a compilation database. See the docs here:
> I'd like to run these tools over our complete code base where the changes
> will affect both header and source files. What is the recommended way to
> limit changes to only my files and not system header files? I expect I can
> limit them to the main file specified by the source manager, however I
> assume that this would prevent changes to my header files.
I simply do match on the path / name of the files for that. Usually project
files have easily detectable paths.
Also note that what I do is key whether I want to replace something on the
file of the original declaration of the 'thing' I want to replace, so that
you don't get inconsistent states.
> How do I prevent a change from being made multiple times while in the same
> translation unit compilation? eg as a result of template or macro
> instantiations or multiple header includes. Is there a recommended way to
> solve this or is it up to the callback to be safe in the case that it is
> run twice on the same piece of code?
That's what the refactoring support in the tooling library is for:
The idea is that you run over all TUs you want to refactor in the same
process. We're working on getting this multi-threaded so that it scales
Another possibility is to output simple diffs from your tool, and use a
little python script to slurp in the changes, unique them and apply them
(that's what we currently do for really large scale MapReduce style
> Thanks for the excellent work you guys are doing,
> Philip Dunstan
> phil at philipdunstan.com
> View this message in context:
> Sent from the Clang Developers mailing list archive at Nabble.com.
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the cfe-dev