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
This commit is contained in:
Andrey Ali Khan Bolshakov 2023-01-07 20:06:15 +03:00 committed by GitHub
parent 849c2a2f55
commit d3e23c367b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 19 deletions

32
iwyu.cc
View File

@ -1696,27 +1696,25 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
if (type->getAs<EnumType>())
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<Derived>::ReportDeclForwardDeclareUse(used_loc, decl,
comment);
}
} else {
if (const auto* template_spec_type =
dyn_cast<TemplateSpecializationType>(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<Derived>::ReportDeclUse(used_loc, decl, comment);
}
if (const auto* template_spec_type =
dyn_cast<TemplateSpecializationType>(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<Derived>::ReportDeclUse(used_loc, decl, comment);
}
}

View File

@ -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<IndirectClass> *t;
// IWYU: IndirectTemplate needs a declaration
// IWYU: IndirectClass needs a declaration
IndirectTemplate<IndirectClass> **ppt;
};