[cfe-dev] Getting the FieldDecl of a template class from a MemberExpr
Douglas Gregor
dgregor at apple.com
Mon Jun 6 10:01:33 PDT 2011
Sent from my iPhone
On May 29, 2011, at 9:31 AM, Adrien Chauve <adrien.chauve at gmail.com> wrote:
> 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());
CXXRecordDecls themselves can also be instantiations of member classes. There's a getInstantiatedFromMember() function (or something like it) to determine when this is the case.
>
> // check the parent of this field is an instanciation of a class template
> if (!parent || parent->getTemplateSpecializationKind() != TSK_ImplicitInstantiation)
> return 0;
Explicit instantiations should also be considered here.
>
> 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;
> }
DeclContex::lookup() can perform this search faster.
>
> // 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/20110606/36c4ee98/attachment.html>
More information about the cfe-dev
mailing list