[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