UdtRecordCompleter shouldn't complete static members' types. static members' types are going to be completed when the types are called in SymbolFile::CompleteType.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
A similar loop exists between a class and class methods, the type of the this parameter usually references the class, and the same is true for any parameters. Is there some existing code to handle this for methods?
For function parameter type and return type, it will not try to complete their types. It just create a skeleton record type. And the skeleton record type is created and cached before it's trying to complete the type.
This defers the completion of static data members by caching them and complete them later
Are you sure that we need to complete static members at all? They have no impact on the layout of the class, so ideally they would only be completed when they are actually used.
Do you mean when completing class type, ignore those static members?
so ideally they would only be completed when they are actually used.
When will they be actually used?
This is what happens now: When TypeSystemClang::DeclContextFindDeclByName is used to find out a decl by name. It parses decls inside each TU until find a decl with the name. Then PdbAstBuilder will try to complete all types and cache them in that PDB file, because we can't filter types by TU.
D82160 also requires constant static member's type width to be known, but this happens when we try to complete the constant static member.
Yes.
so ideally they would only be completed when they are actually used.
When will they be actually used?
In the expression evaluator, for one. I'm not sure if there are any other cases.
This is what happens now: When TypeSystemClang::DeclContextFindDeclByName is used to find out a decl by name. It parses decls inside each TU until find a decl with the name. Then PdbAstBuilder will try to complete all types and cache them in that PDB file, because we can't filter types by TU.
I'm not very familiar with this stuff, but have you checked what dwarf would do under the same circumstances. I would be surprised if the answer is "it completes all static member types".
In the expression evaluator, for one. I'm not sure if there are any other cases.
If we ignore static members when completing class types, we don't know if CompleteType is called for completing a static member whose type is the class or other cases. For example, when we want to complete the type of static members whose type is the class (e.g. A) itself during expression evaluation, we are trying to complete the class A, but we don't know if we should ignore its static members.
I'm not very familiar with this stuff, but have you checked what dwarf would do under the same circumstances. I would be surprised if the answer is "it completes all static member types".
I checked dwarf but still don't understand how it evaluates static members without going into the loop.
I was imagining you would create the static member type as a forward decl -- create some ast like class Member { ... }; class StaticMember; class A { Member m; static StaticMember sm; };. And then you'd get a completion request for StaticMember when the type of A::sm is required.
I'm not very familiar with this stuff, but have you checked what dwarf would do under the same circumstances. I would be surprised if the answer is "it completes all static member types".
I checked dwarf but still don't understand how it evaluates static members without going into the loop.
I think that's because it creates them as forward declarations -- as I outlined above. DWARFASTParserClang::ParseTypeFromDWARF creates a forward-declared type, and ::CompleteTypeFromDwarf completes it. When parsing a class, the dwarf parser calls DWARFDIE::ResolveTypeUID (line 2673 of DWARFASTParserClang.cpp), which (after going through too many layers) ends up in DWARFASTParserClang::ParseTypeFromDWARF.
Also, note that the DWARF parser also has code which should prevent loops in regular members (which should only be possible for malformed inputs).
We simply shouldn't complete the types of static members at all, which is how dwarf does it.
Their types are eventually completed when called by SymbolFile::CompleteType.
This is cool, just one question about the test.
lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp | ||
---|---|---|
8–26 ↗ | (On Diff #414529) | Would it be possible to put this into a new test case, one that does not require running the binary? If we're able to read global variables without a running process (we can do it with elf+dwarf, but I don't know what's the state with coff+pdb), then we could run this test on non-windows hosts as well (which is great for test coverage). |
Testing with image lookup -type
lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp | ||
---|---|---|
8–26 ↗ | (On Diff #414529) | Printing doesn't work with any expression involves :: in NativePDB. So, I changed the test to image lookup -type which also tries to complete given type. |
lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp | ||
---|---|---|
8–26 ↗ | (On Diff #414529) | That's cool, but I see the new test still has a REQUIRES: system-windows. Would it be possible to drop that requirement (if not, then why)? |
Remove REQUIRES: system-windows.
lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp | ||
---|---|---|
8–26 ↗ | (On Diff #414529) | This is not necessary. Removed. |