[cfe-dev] Clang tooling namespace issues

Manuel Klimek klimek at google.com
Fri Dec 5 03:34:57 PST 2014


Also, your snippet looks light it could profit from the refactoring libs we
have in clang.
A nice intro is:
http://eli.thegreenplace.net/2014/07/29/ast-matchers-and-clang-refactoring-tools

On Fri Dec 05 2014 at 11:37:27 AM Nikola Smiljanic <popizdeh at gmail.com>
wrote:

> Hi Anna, if StringData is a C++ class you can call getAsCXXRecordDecl on
> QualType to get the class declaration. Call getQualifier (defined in
> TagDecl base class) on the declaration to access the NestedNameSpecifier.
>
> On Fri, Dec 5, 2014 at 6:33 AM, Anna Herlihy <anna.herlihy at mongodb.com>
> wrote:
>
>> Hi,
>>
>> I'm trying to write a clang compiler tool that will change any functions
>> that take an argument of type StringData by const ref to taking it by
>> value.  I would like to have the transformed argument have the same
>> naming format as the original (i.e. if it's declared without a namespace
>> qualifier, then the rewritten argument should not have one and vice versa).
>> StringData is my string wrapper class.
>>
>> For example, I want to transform:
>>
>> void example(const StringData& d);
>>
>> into:
>>
>> void example(StringData);
>>
>> And I *also* want to be able to transform:
>>
>> void example_ns(const ns::StringData& d);
>>
>> into:
>>
>> void example_ns(ns::StringData);
>>
>>
>> I'm using RecursiveASTVisitor, and in my VisitFunctionDecl function I
>> check for arguments that match my criteria then use the Rewriter class
>> to change the argument from const ref to a value. My problem is that the
>> transformation always writes the full elaborated type, so for const
>> StringData&, instead of changing the argument type to simply StringData,
>> it changes it to class ns::StringData.
>>
>> My code currently looks like this:
>>
>> bool VisitFunctionDecl(FunctionDecl *f) {
>>
>>     for (unsigned int i=0; i<f->getNumParams(); i++) {
>>
>>
>>         ParmVarDecl* p = f->getParamDecl(i);
>>
>>         QualType original_type = p->getOriginalType();
>>
>>         QualType original_nr = original_type.getNonReferenceType();
>>
>>         const IdentifierInfo* id = original_type.getBaseTypeIdentifier();
>>
>>         if (id == NULL) { continue; }
>>
>>
>>         if (!id->getName().compare("StringData") &&
>>
>>             original_type->isReferenceType() &&
>>
>>             original_nr.isConstQualified()) {
>>
>>
>>             original_nr.removeLocalConst();
>>
>>             TheRewriter.ReplaceText(p->getSourceRange(),
>> original_nr.getAsString());
>>
>>         }
>>
>>     }
>>
>>     return true;
>>   }
>>
>>
>>
>> If I run this code on the following example:
>>
>> void example_ns(const ns::StringData& d);
>>
>> using namespace ns;
>> void example(const StringData& d);
>>
>>
>> The result looks like:
>>
>> void example_ns(ns::StringData);
>> using namespace ns;
>> void example(class ns::StringData);
>>
>> But I want the result to look like:
>>
>> void example_ns(ns::StringData);
>> using namespace ns;
>> void example(StringData);
>>
>> Is there a way of finding out if a declaration is made with an explicit
>> namespace qualifier? Is there any way to determine what the actual
>> namespace of a type is? How can I extract the name of the argument type in
>> the same format as it's declared in the original source?
>>
>> I am also working on another tool for identifying namespace dependencies
>> so any advice involving namespaces and RecursiveASTVisitors is welcome :)
>>
>> Thank you!
>>
>> Anna
>>
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>
>>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20141205/676cfdba/attachment.html>


More information about the cfe-dev mailing list