[cfe-dev] Getting the FieldDecl of a template class from a MemberExpr

Adrien Chauve adrien.chauve at gmail.com
Sun May 29 09:31:07 PDT 2011


Thanks a lot!
Here is what I came up with (I didn't make getInstantiatedFrom a member
yet):

/// getInstantiatedFrom - if the parent of this (FieldDecl* d) is
an
/// instanciation of a template class, return the corresponding FieldDecl*
of this
/// template
class.

FieldDecl* getInstantiatedFrom(FieldDecl const * const
d)

{

    ClassTemplateSpecializationDecl const * const parent
=


dyn_cast<ClassTemplateSpecializationDecl>(d->getParent());



    // check the parent of this field is an instanciation of a class
template
    if (!parent || parent->getTemplateSpecializationKind() !=
TSK_ImplicitInstantiation)
        return
0;



    CXXRecordDecl const * const generic_parent
=


parent->getSpecializedTemplate()->getTemplatedDecl();


assert(generic_parent);



    for(CXXRecordDecl::field_iterator f=generic_parent->field_begin(),
e=generic_parent->field_end(); f != e; ++f)

{

        if ((*f)->getNameAsString() ==
d->getNameAsString())

            return
*f;


}



    // should never get
here

    return
0;

}


Is it what you had in mind? I would be glad to make it a patch and add some
tests it it seems ok.

Adrien

On Fri, May 27, 2011 at 23:34, Douglas Gregor <dgregor at apple.com> wrote:

>
> On May 27, 2011, at 2:32 PM, Johannes Schaub (litb) wrote:
>
> > Douglas Gregor wrote:
> >
> >>
> >> On May 27, 2011, at 10:02 AM, Adrien Chauve wrote:
> >>
> >>> Hi,
> >>>
> >>> Using a RecursiveASTVisitor, I've been trying to rename field names
> >>> against some conventions.
> >>>
> >>> Let's say I would like to rename Foo::bar into Foo::m_bar in the
> >>> following code:
> >>>
> >>> template<typename T>
> >>> struct Foo
> >>> {
> >>>    int bar;
> >>> };
> >>>
> >>> int main()
> >>> {
> >>>    Foo<double> foo;
> >>>    foo.bar = 2;
> >>>
> >>>    return 1;
> >>> }
> >>>
> >>>
> >>> In my custom visitor, I implement the following method:
> >>>
> >>> bool VisitMemberExpr(MemberExpr* member)
> >>> {
> >>>    ValueDecl* v = member->getMemberDecl(); // FieldDecl or
> CXXMethodDecl
> >>>    ...
> >>> }
> >>>
> >>> But the FieldDecl I get when visiting the statement corresponding to
> >>> "foo.bar=2;" is Foo<double>::bar, but not Foo::bar.
> >>>
> >>> So my question is: is it possible to get the FieldDecl of Foo<T>::bar
> >>> from the FieldDecl of Foo<double>::bar ? at least when the struct is
> not
> >>> specialized? What happens when the struct is specialized?
> >>
> >> For fields, this is a pain. You'll actually have to look at the type
> that
> >> owns the field (a ClassTemplateSpecializationDecl), check whether it was
> >> instantiated vs. specialized (using getSpecializationKind()) and, if it
> >> was instantiated, retrieve the class template from which is was
> >> instantiated (getSpecializedTemplate()).
> >>
> >
> > I was looking into the doxygen documentations, and I couldn't find how to
> > proceed from that.
> >
> > How to get the correct field decl of the class template that correspond
> to
> > the field decl of the instantiated specialization? Can one just take the
> > std::distance of the field decl iterator for the specialization, and with
> > that, index into the field decl iterator of the class template?
>
> That works, or you can use name lookup.
>
>        - Doug
>
> _______________________________________________
> 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/20110529/1ff89ec1/attachment.html>


More information about the cfe-dev mailing list