-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Constructor call of a sugared type should not consider the underly type as a use #59916
Comments
@llvm/issue-subscribers-clang-include-cleaner |
Because the AST representation of "constructor call" is varied and murky, this feels a bit underspecified. Are we e.g. saying that this code isn't a use of Foo or any of its members? // foo.h
class Foo { public: Foo(); };
// foo2.h
Foo returnsFoo();
// bar.h
#include "foo.h" // unused?
#include "foo2.h"
auto alsoReturnsFoo() -> decltype(returnsFoo()) { return {/*constructor call*/}; } Or are we just saying that a constructor call is really a use of the type, and we should find the best form of the type? |
To be clear, my original description was not correct (fixed), the current implementation treats a constructor call is a use of the constructor decl, rather than the class type. But I think it won't affect our discussion. And it raises question 1: should a constructor call be considered as a use of the constructor decl, or a class type? I'm not sure the reason behind it (to align with the clangd implementation?), and given that we already treat all member expr (including destructor call) as a use of class type, constructor call seems to fit in this model as well.
Yes, it is hard to distinguish an explicitly-spelled constructor call with the current clang AST, we have a simple heuristic in WalkAST.cpp, which is based on the validity of the parenthese or brace. (Question 2: can we improve it in the clang AST? E.g. adding an extra
Given the In today's implementation, we report an (implicit/explicit) reference of a constructor decl, this implies that we never remove the
That's a good and higher-level question, possible answers:
|
I'd also like to highlight the other problem you've in the example above. I believe no matter what conclusions we come to regarding the constructor handling, in the presence of a type-alias all the usages should be attributed to it. Now ignoring the type-alias case and focusing on the constructor calls; per include-what-you-spell (IWYS) policy, unless the constructor call is explicitly spelled in code, with the type name, we shouldn't report the use. e.g. in Sam's example, foo.h is unused and it should be foo2.h's responsibility to include Moreover I don't see useful invariant we can introduce into the code by special casing constructor calls that don't have the type name spelled (one that I can think of is, if the library moves from type I believe the rather useful guarantee here is not treating constructor calls as references when the user code's intent is solely as an opaque type (e.g. through implicit conversions/copies, if we had a This is mostly my gut feeling though (and yes I am planning to write all of these rationale down, I promise soon), so I am also happy to go with other behaviors if there're more compelling arguments toward what invariant we can introduce to code bases with different treatments.
regarding the constructordecl being a reference to constructor vs type, we should be consistent here and make it a reference to its type as well (I don't think treating constructor and other members differently gives us any benefit apart from creating a harder to grasp mental model).
as mentioned, i don't think we need to figure out if a constructor call happened with the spelling of the type, i think we should rather try to figure out whether the user explicitly intended to call the constructor. For such cases, I think it's enough to look at the presence of a brace/paren. |
Per the discussion in #59916. Differential Revision: https://reviews.llvm.org/D141592
Per the discussion in llvm/llvm-project#59916. Differential Revision: https://reviews.llvm.org/D141592
Per the discussion in llvm/llvm-project#59916. Differential Revision: https://reviews.llvm.org/D141592
For the
Bar();
usage in main.cpp, include-cleaner considers both UsingType (Bar
) and theunderlying type (Foo
)Foo
constructor as uses (thus we insert bothfoo.h
, andbar.h
). In this case, we should not consider the underlying typeFoo
as a use.The text was updated successfully, but these errors were encountered: