[cfe-dev] retrieving anonymous struct decl name

John Leidel via cfe-dev cfe-dev at lists.llvm.org
Tue Dec 22 07:46:58 PST 2020


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 <davrecthreads at gmail.com> 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 <cfe-dev at lists.llvm.org> 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
> > cfe-dev at lists.llvm.org
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>


More information about the cfe-dev mailing list