retrieving anonymous struct decl name

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( ??? );
     }
  }
}

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.

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.