Fix template instantiation reporting

Full template specialization type use requires full information about
its template-argument-dependent fields and nested typedefs. But earlier,
it wasn't reported in many cases when template specialization type isn't
written explicitly in non-fwd-decl context.
This commit is contained in:
Bolshakov 2022-07-09 21:21:17 +03:00 committed by Kim Gräsman
parent ac93b84f01
commit 526827957b
3 changed files with 29 additions and 3 deletions

25
iwyu.cc
View File

@ -1665,6 +1665,10 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
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";
@ -2670,6 +2674,17 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
visitor_state_->processed_overload_locs.insert(loc);
}
// Report types needed for template instantiation in cases when template
// specialization type isn't explicitly written in a source code
// in a non-fwd-declarable context (otherwise, they should be reported from
// VisitTemplateSpecializationType), e.g.:
// template <class T> struct S { T t; };
// void fn(const S<Class>& s) { // Forward declarations are sufficient here.
// (void)s.t; // Full 'Class' type is needed due to template instantiation.
// }
void ReportTplSpecComponentTypes(const TemplateSpecializationType*) {
}
// Do not add any variables here! If you do, they will not be shared
// between the normal iwyu ast visitor and the
// template-instantiation visitor, which is almost always a mistake.
@ -4197,6 +4212,16 @@ class IwyuAstConsumer
return true;
}
// --- Handler declared in IwyuBaseASTVisitor.
void ReportTplSpecComponentTypes(const TemplateSpecializationType* type) {
const map<const Type*, const Type*> resugar_map =
GetTplTypeResugarMapForClass(type);
ASTNode node(type);
node.SetParent(current_ast_node());
instantiated_template_visitor_.ScanInstantiatedType(&node, resugar_map);
}
private:
// Class we call to handle instantiated template functions and classes.
InstantiatedTemplateVisitor instantiated_template_visitor_;

View File

@ -1565,17 +1565,17 @@ int main() {
// IWYU: i1_ns::I1_NamespaceClass is...*badinc-i1.h
I1_Class* i1_class_tpl_ctor = new I1_Class(&i1_namespace_class, 1);
// TODO(csilvers): IWYU: I2_Class needs a declaration
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
// IWYU: I1_Struct is...*badinc-i1.h
// IWYU: I1_TemplateClass is...*badinc-i1.h
delete newed_i1_template_class;
// TODO(csilvers): IWYU: I2_Class needs a declaration
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
// IWYU: I1_Struct is...*badinc-i1.h
// IWYU: I1_TemplateClass is...*badinc-i1.h
delete[] newed_i1_template_class_array;
// TODO(csilvers): IWYU: I2_Class needs a declaration
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
// IWYU: I1_Struct is...*badinc-i1.h
// IWYU: I1_TemplateClass is...*badinc-i1.h

View File

@ -90,6 +90,7 @@ void PlacementNewOfTemplate() {
// Make sure we handle it right when we explicitly call the dtor, as well.
// IWYU: ClassTemplate is...*placement_new-i1.h
// IWYU: IndirectClass is...*indirect.h
placement_newed_template->~ClassTemplate();
}