[cfe-dev] Clang tooling namespace issues

Anna Herlihy anna.herlihy at mongodb.com
Thu Dec 4 11:33:41 PST 2014


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20141204/094cc2a5/attachment.html>


More information about the cfe-dev mailing list