[cfe-dev] Clang tooling namespace issues

Anna Herlihy anna.herlihy at mongodb.com
Fri Dec 12 08:04:51 PST 2014


Thank you for the help!! That fixed my problem :)


For anybody interested, what ended up working was:

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();

 Type::TypeClass t = original_nr->getTypeClass();



       if( t == Type::Elaborated ) { // if namespace qualified

            const ElaboratedType* etype = cast<ElaboratedType>(orignal_nr);

            NestedNameSpecifier* name = etype->getQualifier();

            name->print(s, Policy);

       }

       s << id->getName().data();


       TheRewriter.ReplaceText(p->getSourceRange(), s.str());

         }

    }

    return true;
  }


Note that this works with arguments declared as "const StringData&" and
"const ns::StringData&" but not with something like "const class
StringData&".

Thanks again!

On Tue, Dec 9, 2014 at 1:56 PM, Richard Smith <richard at metafoo.co.uk> wrote:

> 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/20141212/bfffb207/attachment.html>


More information about the cfe-dev mailing list