clangd icon indicating copy to clipboard operation
clangd copied to clipboard

Unexpected forward declare on defining pointer/reference

Open JVApen opened this issue 6 months ago • 3 comments

Have a header:

#pragma once
namespace NS
{
     struct MyStructToFWD {};
}

Have another header:

#pragma once
namespace NS
{
     struct NewStruct
     {
         MyStruct^
     };
}

Do autocomplete at the ^. The intention here is to write the following:

#pragma once
namespace NS
{
     struct NewStruct
     {
         MyStructToFWD *str;
     };
}

Result, the auto-completion causes the first header to be included. I would expect the include cleaner to indicate this include is unneeded, though it does not.

Expected result: Whenever auto-completing on (class|struct) Something^, only the name should be added, not the include.

System information

Output of clangd --version: 19

Editor/LSP plugin: VS Code

Operating system: Windows

JVApen avatar May 21 '25 10:05 JVApen

This has a similar challenge to https://github.com/clangd/clangd/issues/639: the user might be declaring a variable of pointer/reference type, but they might be declaring a variable of value type as well, and we don't know at the point at which completion is invoked. In the latter scenario, we'd end up with an error diagnostic due to the type being incomplete.

HighCommander4 avatar May 22 '25 03:05 HighCommander4

I guess this is the difference between standard C (also valid in C++) and standard C++. For C, you have to write struct S s; in order to use S, while C++ only needs S s;. The situations in C++ where you need the include after writing struct/class seem quite limited to me. (I've only seen it once due to a C header)

I'm still processing this issue. What I'm currently thinking of is: (ignoring feasibility)

  • maybe includes shouldn't be added as part of the auto-complete. Instead they can be added on : and ; when the context is clear
  • we might need an explicit action to add an include for a symbol

JVApen avatar Jun 02 '25 07:06 JVApen

For C, you have to write struct S s; in order to use S, while C++ only needs S s;.

I understand that, but I'm not sure how it's relevant to the scenario at issue here:

#pragma once
namespace NS
{
     struct NewStruct
     {
         MyStruct^
     };
}

Do autocomplete at the ^.

Here, you might be writing MyStruct* field; or MyStruct field;. Neither involve the struct keyword, but one of them requires the include.

HighCommander4 avatar Jun 03 '25 04:06 HighCommander4