retrieving anonymous struct decl name

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

retrieving anonymous struct decl name

shirley breuer via cfe-dev
I'm still working on the same issue associated with translating
anonymous struct decl's to non-anonymous structs.  With the same
original example, I have the TagDecl for the nested struct definition.
Is there a way to retrieve the declaration name "first" from the
TagDecl?

typedef struct test_case_t {
  struct {
     int value;
  } first[1];
  int second;
  int third[1];
} test_case_t;

As an example below, I grab the RecordDecl for the top-level struct,
then traverse each member using the decl_iterator.  I have other code
to examine each FieldDecl, but I'm specifically interested in the
following.  If I can dyn_cast to a TagDecl, then I'm looking at the
struct declaration.  I'm trying to retrieve the anonymous
DeclarationName and use it to reset the declaration of the nested
struct and its variable definition. Thoughts?

for(RecordDecl::decl_iterator iter = RD->decls_begin(), end =
RD->decls_end(); iter != end; ++iter) {
  if(TagDecl *TD = dyn_cast<TagDecl>(*iter)){
     if(TD->isThisDeclarationADefinition()){
        // This sets the struct definition and instance name to test_case_t
        // how do I retrieve "first"?
        // this should induce struct first { }; struct first first[1];
        TD->setDeclName( ??? );
     }
  }
}
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: retrieving anonymous struct decl name

shirley breuer via cfe-dev
You cannot get the VarDecl name from the TagDecl; the anonymous struct is placed as its own node and the VarDecls placed subsequently (which is a bit unfortunate, it would be nice if the syntax were more directly represented, but that might present its own problems); but you might benefit from looking at how DeclPrinter handles this tricky case:

https://github.com/llvm-mirror/clang/blob/master/lib/AST/DeclPrinter.cpp#L394 

Basically, while iterating over decls(), you would look for TagDecls for which `isFreeStanding()` returns false, then accumulate the subsequent VarDecls whose “base” type (after removing pointers etc.) is the TagDecl, and when those are exhausted you handle the Tag + VarDecls together as a whole.

Not 100% sure what you ultimately want to do but hope that helps.

> On Dec 20, 2020, at 10:11 PM, John Leidel via cfe-dev <[hidden email]> wrote:
>
> I'm still working on the same issue associated with translating
> anonymous struct decl's to non-anonymous structs.  With the same
> original example, I have the TagDecl for the nested struct definition.
> Is there a way to retrieve the declaration name "first" from the
> TagDecl?
>
> typedef struct test_case_t {
>  struct {
>     int value;
>  } first[1];
>  int second;
>  int third[1];
> } test_case_t;
>
> As an example below, I grab the RecordDecl for the top-level struct,
> then traverse each member using the decl_iterator.  I have other code
> to examine each FieldDecl, but I'm specifically interested in the
> following.  If I can dyn_cast to a TagDecl, then I'm looking at the
> struct declaration.  I'm trying to retrieve the anonymous
> DeclarationName and use it to reset the declaration of the nested
> struct and its variable definition. Thoughts?
>
> for(RecordDecl::decl_iterator iter = RD->decls_begin(), end =
> RD->decls_end(); iter != end; ++iter) {
>  if(TagDecl *TD = dyn_cast<TagDecl>(*iter)){
>     if(TD->isThisDeclarationADefinition()){
>        // This sets the struct definition and instance name to test_case_t
>        // how do I retrieve "first"?
>        // this should induce struct first { }; struct first first[1];
>        TD->setDeclName( ??? );
>     }
>  }
> }
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: retrieving anonymous struct decl name

shirley breuer via cfe-dev
David, I sincerely appreciate the reply!  This is indeed a very
interesting case.  The issue was, our translator modifies certain
global struct definitions and converts their type declarations to
typedefs.  However, for global structs that include member structs (as
was the case above), these should be left alone.  The existing
translator code split the declaration and definition into separate
Decls, so the resulting C code emitted from the translator required
that we go back and name the structures.  Clang subsequently throws a
warning that the inner struct doesn't declare anything (per C11.
6.7.2.1p2).  See example below:

struct test_case_t {
    struct first {
        int value;
    }; // -- warning generated here
    struct first first[1];
    int second;
    int third[1];
};


Per your original suggestion, for each FieldDecl, we caught TagDecl's
that were not FreeStanding and saved their value for future
processing.  When creating the translated struct variable
declarations, we named the variable definition and the backing TagDecl
(dyn_cast to a RecordDecl) using the name same.

for(RecordDecl::decl_iterator iter = RD->decls_begin(), end =
RD->decls_end(); iter != end; ++iter) {
  Decl *StructDecl = nullptr;
  if(FieldDecl *FD = dyn_cast_or_null<FieldDecl>(*iter)) {
    // create new FD
    if(const ElaboratedType * NET =
dyn_cast<ElaboratedType>(SemaRef.Context.getBaseElementType(NewFD->getType())))
{
        if( StructDecl ){
         RecordDecl *MyDecl = dyn_cast<RecordDecl>(StructDecl);
         if( MyDecl )
          MyDecl->setDeclName(FD->getDeclName());
         }
       }
   }
  }else if(TagDecl *TD = dyn_cast<TagDecl>(*iter)){
     if(TD->isThisDeclarationADefinition() && !TD->isFreeStanding()){
       // save StructDecl
     }
  }
}


Its certainly not pretty, but it works for the case that we need.

On Mon, Dec 21, 2020 at 1:22 PM David Rector <[hidden email]> wrote:

>
> You cannot get the VarDecl name from the TagDecl; the anonymous struct is placed as its own node and the VarDecls placed subsequently (which is a bit unfortunate, it would be nice if the syntax were more directly represented, but that might present its own problems); but you might benefit from looking at how DeclPrinter handles this tricky case:
>
> https://github.com/llvm-mirror/clang/blob/master/lib/AST/DeclPrinter.cpp#L394
>
> Basically, while iterating over decls(), you would look for TagDecls for which `isFreeStanding()` returns false, then accumulate the subsequent VarDecls whose “base” type (after removing pointers etc.) is the TagDecl, and when those are exhausted you handle the Tag + VarDecls together as a whole.
>
> Not 100% sure what you ultimately want to do but hope that helps.
>
> > On Dec 20, 2020, at 10:11 PM, John Leidel via cfe-dev <[hidden email]> wrote:
> >
> > I'm still working on the same issue associated with translating
> > anonymous struct decl's to non-anonymous structs.  With the same
> > original example, I have the TagDecl for the nested struct definition.
> > Is there a way to retrieve the declaration name "first" from the
> > TagDecl?
> >
> > typedef struct test_case_t {
> >  struct {
> >     int value;
> >  } first[1];
> >  int second;
> >  int third[1];
> > } test_case_t;
> >
> > As an example below, I grab the RecordDecl for the top-level struct,
> > then traverse each member using the decl_iterator.  I have other code
> > to examine each FieldDecl, but I'm specifically interested in the
> > following.  If I can dyn_cast to a TagDecl, then I'm looking at the
> > struct declaration.  I'm trying to retrieve the anonymous
> > DeclarationName and use it to reset the declaration of the nested
> > struct and its variable definition. Thoughts?
> >
> > for(RecordDecl::decl_iterator iter = RD->decls_begin(), end =
> > RD->decls_end(); iter != end; ++iter) {
> >  if(TagDecl *TD = dyn_cast<TagDecl>(*iter)){
> >     if(TD->isThisDeclarationADefinition()){
> >        // This sets the struct definition and instance name to test_case_t
> >        // how do I retrieve "first"?
> >        // this should induce struct first { }; struct first first[1];
> >        TD->setDeclName( ??? );
> >     }
> >  }
> > }
> > _______________________________________________
> > cfe-dev mailing list
> > [hidden email]
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev