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

Richard Smith richard at metafoo.co.uk
Fri May 30 15:32:40 PDT 2014


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/20140530/846721ce/attachment.html>


More information about the cfe-dev mailing list