<div dir="ltr">Hi,<div><br></div><div>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.  <span style="font-family:arial,helvetica,sans-serif">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.</span></div><div><span style="font-family:arial,helvetica,sans-serif"><br></span></div><div><span style="font-family:arial,helvetica,sans-serif">For example, I want to transform: </span></div><div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><font face="monospace">void example(const StringData& d);</font></blockquote></div></div><div>into:</div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><span style="font-family:monospace">void example(StringData);</span></div><div><span style="font-family:monospace"><br></span></div></blockquote><font face="arial, helvetica, sans-serif">And I <i>also</i> want to be able to transform:</font><div><div><div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><font face="monospace">void example_ns(const ns::StringData& d);</font></blockquote></div><div>into:</div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><span style="font-family:monospace">void example_ns(ns::StringData);</span></blockquote><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">I'm using RecursiveASTVisitor, and in my </font><font face="monospace">VisitFunctionDecl</font><font face="arial, helvetica, sans-serif"> function I check for arguments </font><span style="font-family:arial,helvetica,sans-serif">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 </span><span style="font-family:monospace">const StringData&, </span><span style="font-family:arial,helvetica,sans-serif">instead of changing the argument type </span><font face="arial, helvetica, sans-serif">to simply </font><font face="monospace">StringData</font><font face="arial, helvetica, sans-serif">, it changes it to </font><font face="monospace">class ns::StringData</font><font face="arial, helvetica, sans-serif">.</font></div><div><span style="font-family:arial,helvetica,sans-serif"><br></span></div><div><span style="font-family:arial,helvetica,sans-serif">My code currently looks like this:</span></div><div><span style="font-family:arial,helvetica,sans-serif"><br></span></div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><span style="font-family:monospace">bool VisitFunctionDecl(FunctionDecl *f) {</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">    for (unsigned int i=0; i<f->getNumParams(); i++) {</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><font face="monospace"><br></font><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">        ParmVarDecl* p = f->getParamDecl(i);</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">        QualType original_type = p->getOriginalType();</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">        QualType original_nr = original_type.getNonReferenceType();</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">        const IdentifierInfo* id = original_type.getBaseTypeIdentifier();</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">        if (id == NULL) { continue; }</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><font face="monospace"><br></font><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">        if (!id->getName().compare("StringData") &&</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">            original_type->isReferenceType() &&</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">            original_nr.isConstQualified()) {</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><font face="monospace"><br></font><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">            original_nr.removeLocalConst();</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">            TheRewriter.ReplaceText(p->getSourceRange(), original_nr.getAsString());</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">        }</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">    }</span><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><span style="font-family:monospace">    return true;</span><br><font face="monospace">  }</font></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><font face="monospace"><br></font><font face="monospace"><br></font></blockquote></blockquote>If I run this code on the following example: </div><div><font face="monospace"><br></font></div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><div><font face="monospace">void example_ns(const ns::StringData& d);</font></div></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><div><font face="monospace">using namespace ns;</font></div><div><font face="monospace">void example(const StringData& d);</font></div></div></div></blockquote></div><div><br></div><div>The result looks like:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><font face="monospace">void example_ns(ns::StringData);<br>using namespace ns;<br>void example(class ns::StringData);<br><br></font></blockquote><div>But I want the result to look like:</div><div><br></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><span style="font-family:monospace">void example_ns(ns::StringData);</span></div></div></div></div><div><div><div><div><span style="font-family:monospace">using namespace ns;</span></div></div></div></div><div><div><div><div><span style="font-family:monospace">void example(StringData);</span></div></div></div></div><div><span style="font-family:monospace"><br></span></div></blockquote><div><div><div><div>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?</div><div><br></div><div>I am also working on another tool for identifying namespace dependencies so any advice involving namespaces and RecursiveASTVisitors is welcome :)</div><div><br></div><div>Thank you!</div><div><br></div><div>Anna</div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div></div></blockquote></div></div></div></div>