[cfe-dev] Clang tooling namespace issues

Richard Smith richard at metafoo.co.uk
Tue Dec 9 10:56:16 PST 2014


On Tue, Dec 9, 2014 at 7:52 AM, Anna Herlihy <anna.herlihy at mongodb.com>
wrote:

> Thank you for getting back to me! Unfortunately, when I call
> getQualifier() on the CXXRecordDecl it always returns null. I tried calling
> it for my own class, ns::StringData, but also std::String and both cases
> return null.
>

CXXRecordDecl::getQualifier gives you this:

struct ns::Foo {};
       ^^^^

You want ElaboratedType::getQualifier(), which gives you this:

void f(ns::Foo);
       ^^^^


> I ran:
>
> QualType original_type = p->getOriginalType();
>
> QualType nonref_type = original_type.getNonReferenceType();
>
> nonref_type.removeLocalConst();
> CXXRecordDecl* decl = nonref_type->getAsCXXRecordDecl();
> NestedNameSpecifier* name = decl->getQualifier();
> if( name == NULL ) {
>       printf("null name: %s\n", nonref_type.getAsString().c_str());
> }
>
>
> on:
>
> void std_ns(const std::string& d);
> void strdata_ns(const mongo::StringData& d);
>
> name is always NULL. Any suggestions on why this might be happening?
>
> Thank you!
>
> On Fri, Dec 5, 2014 at 5:31 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/20141209/e1cd86ec/attachment.html>


More information about the cfe-dev mailing list