[cfe-dev] Modification of a StringLiteral (SemaConsumer - RecursiveASTVisitor - TreeTransform)

Timothée Vandeput timothee.vandeput at gmail.com
Mon Jun 2 06:52:53 PDT 2014


Hello Richard,

I tried your suggestion but I get the following error when the method
*AddInitializerToDecl
*is invoked on the *FieldDecl *:
*test3.cpp:32:9: error: illegal initializer (only variables can be
initialized)*

My code does the following :

*class MyClass *
*{*
*      MyOtherClass myVar {"StringToModify"};*
*}*

In the mean time, I found a solution without a TreeTransform. My initial
problem (wrong const char array length) is solved by setting a new type on
the StringLiteral.

However, if you have any idea on how to get this working with a
TreeTransform, I am willing to try.

Thanks



On Fri, May 30, 2014 at 6:32 PM, Richard Smith <richard at metafoo.co.uk>
wrote:

> On Fri, May 30, 2014 at 10:52 AM, Timothée Vandeput <
> timothee.vandeput at gmail.com> wrote:
>
>> Hello Richard,
>>
>>  *The AST is neither designed nor intended to support in-place
>>> modification -- it's supposed to be essentially immutable once created.
>>> TreeTransform is a better approach (since it creates new AST rather than
>>> updating existing AST nodes in-place).*
>>>
>>
>> This is what I have been reading here on previous messages, hence our
>> attempt to use TreeTransform.
>>
>>
>>> *In your overridden TransformStringLiteral, how are you creating the new
>>> StringLiteral? We don't seem to have any relevant functions on Sema for
>>> this, so I think you'd need to compute the relevant type yourself and call
>>> StringLiteral::Create.*
>>>
>>
>> This is what we tried, here is the code snippet of our TreeTransform
>> class :
>>
>> *class HmIdTransform : public TreeTransform<HmIdTransform>*
>> *{*
>> * Sema& m_Sema;*
>>  * ASTContext& m_Context;*
>> * std::string m_NewString;*
>>
>> *public:*
>> * HmIdTransform(Sema& semaRef, std::string newString)*
>> * : TreeTransform(semaRef)*
>> * , m_Sema(semaRef)*
>> * , m_Context(semaRef.getASTContext())*
>> * , m_NewString(newString)*
>> * {*
>>
>> * }*
>>
>> * bool AlwaysRebuild() { return true; }*
>>
>> * ExprResult TransformStringLiteral(StringLiteral* strLiteral)*
>> * {*
>> * QualType StrType = m_Context.getConstantArrayType(m_Context.CharTy,
>> llvm::APInt(32, m_NewString.size() + 1), ArrayType::Normal, 0);*
>>
>> * return m_Sema.Owned(StringLiteral::Create(m_Context, m_NewString,
>> StringLiteral::Ascii, false, StrType, strLiteral->getLocStart()));*
>> * }*
>> *};*
>>
>> Here is an extract of our RecursiveASTVisitor::TraverseFieldDecl method :
>>
>> *bool TraverseFieldDecl(FieldDecl* decl)*
>> *{*
>> * if(decl->hasInClassInitializer())*
>> * {*
>> * Expr* initializer = decl->getInClassInitializer();*
>>
>> * if(initializer && initializer->children())*
>> * {*
>> * HmIdTransform initTransform(m_CI.getSema(), "ModifiedString");*
>>
>> * initTransform.TransformInitializer(initializer, true);*
>>
>
> This returns the transformed initializer; you need to do something with
> the result. (This, too, will require modifying the AST, so it's not a
> particularly safe operation.)
>
> I'm not sure if this will be sufficient, but you could try:
>
> decl->removeInClassInitializer();
> SemaRef.AddInitializerToDecl(decl, /*result of transform*/, false, false);
>
>
>> * }*
>> * }*
>>
>> * return true;*
>> *}*
>>
>> Now, it seems the node doesn't get rebuild, do we have to invoke a method
>> to rebuild the modified node?
>> I though the TreeTransform would do it (knowing that it has a reference
>> to the Sema) but I guess I am mistaken.
>>
>> Thanks for your help !
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140602/cc6cf93e/attachment.html>


More information about the cfe-dev mailing list