https://github.com/Michael137 commented:

I have the suspicion that this could be done simpler.

`CXXRecordDecl::lookupInBases` is already perfectly capable of finding field in 
anonymous structures in bases. That's why the expression evaluator is able to 
find them just fine.

I think the actual problem lies in our logic that iterates the `CXXBasePaths` 
after the `lookupInBases` lookup.

The field of the anonymous structure *is found* by `lookupInBases`. It is an 
`IndirectFieldDecl`. But we fail to extract it in:
```
              for (clang::DeclContext::lookup_iterator I = path->Decls, E;
                   I != E; ++I) {
                child_idx = GetIndexForRecordChild(
                    parent_record_decl, *I, omit_empty_base_classes);
                if (child_idx == UINT32_MAX) {
                  child_indexes.clear();
                  return 0;
```

Here `GetIndexForRecordChild` doesn't correctly get the index of the 
`IndirectFieldDecl`:

```
   6702   clang::RecordDecl::field_iterator field, field_end;                   
                          
   6703   for (field = record_decl->field_begin(), field_end = 
record_decl->field_end();                  
   6704        field != field_end; ++field, ++child_idx) {                      
                          
-> 6705     if (field->getCanonicalDecl() == canonical_decl)                    
                          
   6706       return child_idx;                                                 
                          
   6707   }                                                                     
                          
   6708                                                                         
                          
   6709   return UINT32_MAX;                                                    
                          
   6710 }                                                                       
                          
   6711                                                                         
                          
   6712 // Look for a child member (doesn't include base classes, but it does 
include                     
   6713 // their members) in the type hierarchy. Returns an index path into     
                          
   6714 // "clang_type" on how to reach the appropriate member.                 
                          
   6715 //                                                                      
                          
Target 0: (lldb) stopped.                                                       
                          
(lldb) p field->getCanonicalDecl()->dump()                                      
                          
FieldDecl 0x7e9f01418 <<invalid sloc>> <invalid sloc> implicit 
'Base::(anonymous struct)'                 
(lldb) p canonical_decl->dump()                                                 
                          
IndirectFieldDecl 0x7e9f014c8 <<invalid sloc>> <invalid sloc> implicit x 'int'  
                          
|-Field 0x7e9f01418 field_index 0 'Base::(anonymous struct)'                    
                          
`-Field 0x7e9f013c0 'x' 'int'                                                   
                          
```

I haven't fully thought this through, but could we adjust 
`GetIndexForRecordChild` to look into unwrap the anonymous union?

We can fish out the underlying `FieldDecl`s in both cases:
```
(lldb) p ((clang::IndirectFieldDecl*)canonical_decl)->getAnonField()
(clang::FieldDecl *) 0x0000000c563293c0
(lldb) p field->getType()->getAsCXXRecordDecl()->field_begin()
(clang::RecordDecl::field_iterator) {
  Current = {
    Current = 0x0000000c563293c0
  }
}
(lldb) p field->getType()->getAsCXXRecordDecl()->field_begin()->dump()
FieldDecl 0xc563293c0 <<invalid sloc>> <invalid sloc> x 'int'
```

So in pseudo-code, maybe the function could look something like:
```
uint32_t TypeSystemClang::GetIndexForRecordChild(
    const clang::RecordDecl *record_decl, clang::NamedDecl *canonical_decl,
    bool omit_empty_base_classes) {
  uint32_t child_idx = TypeSystemClang::GetNumBaseClasses(
      llvm::dyn_cast<clang::CXXRecordDecl>(record_decl),
      omit_empty_base_classes);

  clang::RecordDecl::field_iterator field, field_end;
  for (field = record_decl->field_begin(), field_end = record_decl->field_end();
       field != field_end; ++field, ++child_idx) {
    IndirectFieldDecl * indirect_decl = 
llvm::dyn_cast<IndirectFieldDecl>(canonical_decl);
    if (field is unnamed && indirect_decl) {
      for (anon_field : fields of anonymous structure)
         if (anon_field == canonical_decl->getAnonField())
            return child_idx;
    } else if (field == canonical_decl)
      return child_idx;
  }

  return UINT32_MAX;
}
```
Might need to adjust the `child_idx` calculation here. But hopefully that 
conveys the overall idea.

Let me know if you have any questions or if you think this doesn't work

https://github.com/llvm/llvm-project/pull/158256
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to