When you have a DIA interface for struct S, can you just call findChildren<PDBSymbolTypeUDT>()?  Will that enumerate tge unnamed struct?  The fact that pdbutil doesn’t is only an indication of how the printing code behaves, you shouldn’t interpret anything about what information is available from it<br><div class="gmail_quote"><div dir="ltr">On Wed, Jul 25, 2018 at 1:55 AM Aleksandr Urakov via Phabricator <<a href="mailto:reviews@reviews.llvm.org">reviews@reviews.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">aleksandr.urakov added inline comments.<br>
<br>
<br>
================<br>
Comment at: lit/SymbolFile/PDB/Inputs/ClassLayoutTest.cpp:37<br>
+  };<br>
+  union {  // Test unnamed union. MSVC treats it as `int a; float b;`<br>
+    int a;<br>
----------------<br>
aleksandr.urakov wrote:<br>
> aleksandr.urakov wrote:<br>
> > Hui wrote:<br>
> > > aleksandr.urakov wrote:<br>
> > > > Here is a problem. `MicrosoftRecordLayoutBuilder` asserts every field or base offset, but in our case fields `a` and `b` are treated as `struct Complex`'s fields, not `union`'s, so lldb crashes in debug on this. I can't find enough info in PDB to restore the unnamed union here. Do you have any ideas about it?<br>
> > > <br>
> > > Based on MSVC cl yielded PDB, you could have full information to restore the unnamed UDT.<br>
> > > <br>
> > > From my experience, PDB yielded by clang-cl  (/Z7 or /Zi) is slightly different from the one by cl.<br>
> > > <br>
> > > Both contain information about forwarded unnamed UDT.<br>
> > > However PDB yielded by clang-cl  more or less lacks the member information.  See below.<br>
> > > <br>
> > > The CodeView info is good. Maybe you need to look at LLC?<br>
> > > <br>
> > > CodeView <br>
> > >  <br>
> > > ```<br>
> > > FieldList (0x1044) {<br>
> > >     TypeLeafKind: LF_FIELDLIST (0x1203)<br>
> > >     DataMember {<br>
> > >       TypeLeafKind: LF_MEMBER (0x150D)<br>
> > >       AccessSpecifier: Public (0x3)<br>
> > >       Type: int (0x74)<br>
> > >       FieldOffset: 0x0<br>
> > >       Name: a<br>
> > >     }<br>
> > >     DataMember {<br>
> > >       TypeLeafKind: LF_MEMBER (0x150D)<br>
> > >       AccessSpecifier: Public (0x3)<br>
> > >       Type: float (0x40)<br>
> > >       FieldOffset: 0x0<br>
> > >       Name: b<br>
> > >     }<br>
> > >   }<br>
> > > <br>
> > > Union (0x1045) {<br>
> > >     TypeLeafKind: LF_UNION (0x1506)<br>
> > >     MemberCount: 2<br>
> > >     Properties [ (0x608)<br>
> > >       HasUniqueName (0x200)<br>
> > >       Nested (0x8)<br>
> > >       Sealed (0x400)<br>
> > >     ]<br>
> > >     FieldList: <field list> (0x1044)<br>
> > >     SizeOf: 4<br>
> > >     Name: Complex::<unnamed-tag><br>
> > >     LinkageName: .?AT<unnamed-type-$S2>@Complex@@<br>
> > >   }<br>
> > > <br>
> > > ```<br>
> > > <br>
> > > llvm-pdbutil  pdb  (clang-cl /z7)<br>
> > > <br>
> > > (found unnamed symbol, however size = 0, they will be just ignored. See PDBASTParser.cpp #259<br>
> > > The size should not be zero) <br>
> > > <br>
> > > <br>
> > > ```<br>
> > >     struct Complex::<unnamed-tag> [sizeof = 0] {}<br>
> > > <br>
> > >     union Complex::<unnamed-tag> [sizeof = 0] {}<br>
> > > <br>
> > >  struct Complex [sizeof = 728] {<br>
> > >       data +0x00 [sizeof=720] _List* array[90]<br>
> > >       data +0x2d0 [sizeof=4] int x<br>
> > >       data +0x2d4 [sizeof=4] int a<br>
> > >       data +0x2d4 [sizeof=4] float b<br>
> > >     }<br>
> > > <br>
> > > ```<br>
> > > <br>
> > > llvm-pdbutil pdb ( cl /z7)<br>
> > > <br>
> > > ( you have full information to restore unnamed) <br>
> > > ```<br>
> > > <br>
> > > struct Complex [sizeof = 728] {<br>
> > >       data +0x00 [sizeof=720] _List* array[90]<br>
> > >       data +0x2d0 [sizeof=4] int x<br>
> > >       data +0x2d4 [sizeof=4] int a<br>
> > >       data +0x2d4 [sizeof=4] float b<br>
> > >     }<br>
> > > <br>
> > >     Total padding 3 bytes (25% of class size)<br>
> > >     Immediate padding 3 bytes (25% of class size)<br>
> > > <br>
> > >     struct Complex::<unnamed-tag> [sizeof = 4] {<br>
> > >       data +0x00 [sizeof=4] int x<br>
> > >     }<br>
> > > <br>
> > >     union Complex::<unnamed-tag> [sizeof = 4] {<br>
> > >       data +0x00 [sizeof=4] int a<br>
> > >       data +0x00 [sizeof=4] float b<br>
> > >     }<br>
> > > ```<br>
> > > <br>
> > > <br>
> > Thank you! But what means `LLC`?<br>
> I have figured that out, sorry. I usually use disassembly tools for this purpose.<br>
I have just dumped two PDBs, one was produced with `cl` and `link`, and other with `clang-cl` and `lld-link` with the same keys (`/Zi /GS- /c` for compilation, `/nodefaultlib /debug:full /entry:main` for linking). I have compiled the source:<br>
<br>
```<br>
struct S {<br>
  struct {<br>
    char a;<br>
    short b;<br>
  };<br>
  short c;<br>
  union {<br>
    short d;<br>
    int e;<br>
  };<br>
};<br>
<br>
int main() {<br>
  S ss[sizeof(S)];<br>
  return 0;<br>
}<br>
```<br>
<br>
and have retrieved identical type infos from PDBs:<br>
<br>
```<br>
struct S::<unnamed-tag> [sizeof = 0] {}<br>
<br>
union S::<unnamed-tag> [sizeof = 0] {}<br>
<br>
struct S [sizeof = 12] {<br>
  data +0x00 [sizeof=1] char a<br>
  <padding> (1 bytes)<br>
  data +0x02 [sizeof=2] short b<br>
  data +0x04 [sizeof=2] short c<br>
  <padding> (2 bytes)<br>
  data +0x08 [sizeof=2] short d<br>
  data +0x08 [sizeof=4] int e<br>
}<br>
Total padding 3 bytes (25% of class size)<br>
Immediate padding 3 bytes (25% of class size)<br>
<br>
struct S::<unnamed-tag> [sizeof = 4] {<br>
  data +0x00 [sizeof=1] char a<br>
  <padding> (1 bytes)<br>
  data +0x02 [sizeof=2] short b<br>
}<br>
Total padding 1 bytes (25% of class size)<br>
Immediate padding 1 bytes (25% of class size)<br>
<br>
union S::<unnamed-tag> [sizeof = 4] {<br>
  data +0x00 [sizeof=2] short d<br>
  data +0x00 [sizeof=4] int e<br>
}<br>
```<br>
<br>
So it seems that both `cl` and `clang` emit enough info to restore the layout of unnamed unions or structs. But we also need to:<br>
<br>
- Find a location of unnamed fields of such types in the outer structure (`S` in our case);<br>
- Somehow drop fields `a`, `b`, `d` and `e` from it (because we will place the unnamed fields of the unnamed types there).<br>
<br>
And I can't find enough info for that. How do you think, is it possible?<br>
<br>
<br>
<a href="https://reviews.llvm.org/D49410" rel="noreferrer" target="_blank">https://reviews.llvm.org/D49410</a><br>
<br>
<br>
<br>
</blockquote></div>