[Lldb-commits] [lldb] [lldb][DWARFASTParserClang] Resolve nested types when parsing structures (PR #66879)

Greg Clayton via lldb-commits lldb-commits at lists.llvm.org
Sat Sep 23 20:49:53 PDT 2023


clayborg wrote:

> > I didn't see much explanation as to why this is needed in the bug report.
> 
> The motivating example is something like:
> 
> ```
> struct Info {
>   enum Mask : uintptr_t {
>     Enum
>   };
> }
> ```
> 
> `expr Info::Mask::Enum`.
> 
> > Is there a reason we need to complete nested types within a type? Seems like we can put that off until later. Right now if you parse a member function, any types it needs will be parsed lazily and only if needed, which is ok. If we start completing all types within types without ever needing to actually use then, it will make debugging slower and cause our memory usage to grow.
> 
> LLDB will first resolve the `Info` structure (and all its member fields, but not nested types). When clang looks for `Mask`, it wants to find it in a direct lookup into the `Info` DeclContext. But that lookup will fail because we never created the decls for the nested type. There is no fallback to the external source in such a case unfortunately so LLDB never has the chance to correct this. There was no obvious point to which we could defer completing the nested type when completing the outer. Maybe adding that external source fallback? But I might've missed something obvious. A potential option would be to limit the completion performed in this patch to enums, though a general solution would be nice.

What we do for classes is we create forward declarations for them at first. As soon as someone wants to know more, we complete the type via the external source interface. This works for expressions since this is what precomiled headers do, it also works with our CompilerType as we can ask for the forward type, the layout type, or the complete type. I wonder if we can make this work for enums as well. 

I am worried about a class that contains many types. Usually when we need to know something about a type, like in your example above, we will get a callback to the ClangExternalASTSourceCallbacks methods:
```
  void FindExternalLexicalDecls(
      const clang::DeclContext *DC,
      llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
      llvm::SmallVectorImpl<clang::Decl *> &Result) override;

  bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
                                      clang::DeclarationName Name) override;
```
So if you typed Info::Mask::Enum, the expression parser will first ask about "Info" with no containing decl context (or maybe it specifies the translation unit decl context to indicate it is a root type) and we will return the "struct Info". Then it would call FindExternalVisibleDeclsByName() with the DeclContext set to "struct Info" and we will find "Mask" inside of this type, then it will ask about "Enum" within the "Info::Mask" type and it should be in the type definition. Maybe some isn't working correctly for enums in this lookup mechanism?



https://github.com/llvm/llvm-project/pull/66879


More information about the lldb-commits mailing list