From d3e23c367be84ad74cefa9829809a8cd29dc4495 Mon Sep 17 00:00:00 2001 From: Andrey Ali Khan Bolshakov <32954549+bolshakov-a@users.noreply.github.com> Date: Sat, 7 Jan 2023 20:06:15 +0300 Subject: [PATCH] Fwd decls for explicit types only Report fwd-decls only for explicitly written types There is no point in reporting forward-declaration of a type when just its pointer is used and the type is not explicitly written in the source. Explicitly written pointer types are handled, e.g., in VisitTemplateSpecializationType and VisitTagType. Add test cases for redundant fwd-decl absence --- iwyu.cc | 32 +++++++++++++++----------------- tests/cxx/array.cc | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/iwyu.cc b/iwyu.cc index c65d6e7..f765e54 100644 --- a/iwyu.cc +++ b/iwyu.cc @@ -1696,27 +1696,25 @@ class IwyuBaseAstVisitor : public BaseAstVisitor { if (type->getAs()) return; + // Types in fwd-decl-context should be ignored here and reported from more + // specialized places, i.e. when they are explicitly written. But in fact, + // this check is redundant because TypeToDeclAsWritten returns nullptr for + // pointers and references. + if (IsPointerOrReferenceAsWritten(type)) + return; + // Map private types like __normal_iterator to their public counterpart. type = MapPrivateTypeToPublicType(type); // For the below, we want to be careful to call *our* // ReportDeclUse(), not any of the ones in subclasses. - if (IsPointerOrReferenceAsWritten(type)) { - type = RemovePointersAndReferencesAsWritten(type); - if (const NamedDecl* decl = TypeToDeclAsWritten(type)) { - VERRS(6) << "(For pointer type " << PrintableType(type) << "):\n"; - IwyuBaseAstVisitor::ReportDeclForwardDeclareUse(used_loc, decl, - comment); - } - } else { - if (const auto* template_spec_type = - dyn_cast(Desugar(type))) { - this->getDerived().ReportTplSpecComponentTypes(template_spec_type); - } - if (const NamedDecl* decl = TypeToDeclAsWritten(type)) { - decl = GetDefinitionAsWritten(decl); - VERRS(6) << "(For type " << PrintableType(type) << "):\n"; - IwyuBaseAstVisitor::ReportDeclUse(used_loc, decl, comment); - } + if (const auto* template_spec_type = + dyn_cast(Desugar(type))) { + this->getDerived().ReportTplSpecComponentTypes(template_spec_type); + } + if (const NamedDecl* decl = TypeToDeclAsWritten(type)) { + decl = GetDefinitionAsWritten(decl); + VERRS(6) << "(For type " << PrintableType(type) << "):\n"; + IwyuBaseAstVisitor::ReportDeclUse(used_loc, decl, comment); } } diff --git a/tests/cxx/array.cc b/tests/cxx/array.cc index aec7848..c189980 100644 --- a/tests/cxx/array.cc +++ b/tests/cxx/array.cc @@ -18,9 +18,13 @@ class A { IndirectClass *getIndirectClass(int i) { // IWYU: IndirectClass is...*indirect.h (void)sizeof(b[i]); // requires full type - // IWYU: IndirectClass needs a declaration // IWYU: IndirectClass is...*indirect.h (void)sizeof(&(b[i])); // requires full type + + // Neither fwd-declaration nor full type is needed for array of pointers + // indexing and pointer size taking. + (void)sizeof(pp[i]); + // IWYU: IndirectClass is...*indirect.h return &(b[i]); } @@ -31,10 +35,14 @@ class A { // IWYU: IndirectTemplate is...*indirect.h // IWYU: IndirectClass is...*indirect.h (void)sizeof(t[i]); // requires full type - // IWYU: IndirectTemplate needs a declaration // IWYU: IndirectTemplate is...*indirect.h // IWYU: IndirectClass is...*indirect.h (void)sizeof(&(t[i])); // requires full type + + // Neither fwd-declaration nor full type is needed for array of pointers + // indexing and pointer size taking. + (void)sizeof(ppt[i]); + // IWYU: IndirectTemplate is...*indirect.h // IWYU: IndirectClass is...*indirect.h return &(t[i]); @@ -42,9 +50,14 @@ class A { // IWYU: IndirectClass needs a declaration IndirectClass *b; + // IWYU: IndirectClass needs a declaration + IndirectClass **pp; // IWYU: IndirectTemplate needs a declaration // IWYU: IndirectClass needs a declaration IndirectTemplate *t; + // IWYU: IndirectTemplate needs a declaration + // IWYU: IndirectClass needs a declaration + IndirectTemplate **ppt; };