-
Notifications
You must be signed in to change notification settings - Fork 390
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
<ext/type_traits.h>
suggested for no apparent reason
#1613
Comments
<ext/type_traits.h>
suggested for no apparently reason<ext/type_traits.h>
suggested for no apparent reason
Reduced: // A.h
struct A {
typedef int Int;
};
// getInt.h
#include "A.h"
A::Int getInt();
// main.cpp
#include "getInt.h"
int main() {
return []{ return getInt(); }();
} IWYU wrongly reports |
An obvious way to fix it is just ignoring lambda conversion operators during traversal, like this: --- a/iwyu.cc
+++ b/iwyu.cc
@@ -1634,6 +1634,12 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
return true;
}
+ bool TraverseCXXConversionDecl(clang::CXXConversionDecl* decl) {
+ if (current_ast_node()->template GetAncestorAs<clang::LambdaExpr>(2))
+ return true;
+ return Base::TraverseCXXConversionDecl(decl);
+ }
+ But this looks like an ad-hoc. For example, it doesn't handle implicit declarations of capture variables, like in this case: (void)[i = getInt()]{}; Another solution is to skip any sugar (not interesting for IWYU in the sense that it doesn't "provide" types) in types not explicitly written in the source (which are handled by --- a/iwyu.cc
+++ b/iwyu.cc
@@ -4289,6 +4289,13 @@ class IwyuAstConsumer
// --- Visitors of types derived from Type.
+ bool TraverseType(QualType type) {
+ if (type.isNull())
+ return true;
+ const Type* desugared = Desugar(type.getTypePtr());
+ return Base::TraverseType(QualType{desugared, 0});
+ }
+ This seems to be more correct. In this form, it causes a bug with exception specifications which is easy to fix, however. Note that this handler should be placed into |
I was playing around with this, and see that with the desugaring type traversal, we get a forward-decl use reported for exception specs, and on mainline we get a full use reported. The only difference I can see in the AST is the presence of an |
--- a/iwyu.cc
+++ b/iwyu.cc
@@ -2435,7 +2435,7 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
for (FunctionProtoType::exception_iterator it =
fn_type->exception_begin();
it != fn_type->exception_end(); ++it)
- if (it->getTypePtr() == type) { // *we're* an exception decl
+ if (GetCanonicalType(it->getTypePtr()) == GetCanonicalType(type)) { // *we're* an exception decl |
I was about to argue that the naked Btw, I wonder if my old idea about doing this as part of traversal would make this more obvious;
(very pseudo, but you get the idea) |
I like it too. It looks more straightforward. |
diff --git a/iwyu.cc b/iwyu.cc
index 6741a2d..4e00465 100644
--- a/iwyu.cc
+++ b/iwyu.cc
@@ -2435,7 +2435,8 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
for (FunctionProtoType::exception_iterator it =
fn_type->exception_begin();
it != fn_type->exception_end(); ++it)
- if (it->getTypePtr() == type) { // *we're* an exception decl
+ if (GetCanonicalType(it->getTypePtr()) ==
+ GetCanonicalType(type)) { // *we're* an exception decl
current_ast_node()->set_in_forward_declare_context(false);
break;
}
@@ -4289,6 +4290,13 @@ class IwyuAstConsumer
// --- Visitors of types derived from Type.
+ bool TraverseType(QualType type) {
+ if (type.isNull())
+ return true;
+ const Type* desugared = Desugar(type.getTypePtr());
+ return Base::TraverseType(QualType{desugared, 0});
+ }
+
bool VisitTypedefType(TypedefType* type) {
if (CanIgnoreCurrentASTNode())
return true; Unfortunately this still recommends we include
The original testcase no longer complains, though. |
For standards later than |
I think that some correct handling of --- a/iwyu.cc
+++ b/iwyu.cc
@@ -4296,6 +4296,16 @@ class IwyuAstConsumer
return Base::TraverseType(QualType{desugared, 0});
}
+ bool TraverseTypeLoc(TypeLoc typeloc) {
+ if (typeloc.isNull())
+ return true;
+ if (typeloc.getBeginLoc() == typeloc.getEndLoc()) {
+ const Type* desugared = Desugar(typeloc.getTypePtr());
+ return Base::TraverseTypeLoc(TypeLoc{desugared, typeloc.getOpaqueData()});
+ }
+ return Base::TraverseTypeLoc(typeloc);
+ }
+ but causes crashes in other cases. |
If I change
str()
to returnbool
instead it is no longer suggested.Happens with 0.23dev and I can reproduce it with back to 0.20 (no earlier binaries to test with).
The text was updated successfully, but these errors were encountered: