Skip to content

Commit

Permalink
Report types needed to form aliased type
Browse files Browse the repository at this point in the history
When substituting concrete types into alias template, the resulting type
should be well-formed even if used in forward-declarable context. I. e.,
the full template argument type is needed if used e. g. in nested name
specifier or in `sizeof(T)` expression. The resulting canonical type may
still be forward-declarable.

To ensure this, the aliased type is scanned by
`InstantiatedTemplateVisitor`. When the alias is used in fwd-declarable
context, `IwyuBaseAstVisitor::VisitTemplateSpecializationType` calls
`set_in_forward_declare_context(true)` on the current node prior to that
scan, hence the resulting type should not be reported, only its
internals should be (because of the calls of
`set_in_forward_declare_context(false)` during the traversal). When
the aliased type is fully used, there may be some redundancy
in reporting.

If someone considers that such a scheme is fragile, or doesn't work
by some reason, a `set_in_forward_declare_context(true)` call may be
placed into the `if (type->isTypeAlias())` statement body inside
`TraverseTemplateSpecializationTypeHelper`.
  • Loading branch information
bolshakov-a committed Jan 21, 2024
1 parent bb1b82a commit c6377ea
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
5 changes: 4 additions & 1 deletion iwyu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3090,6 +3090,9 @@ class InstantiatedTemplateVisitor
if (CanIgnoreCurrentASTNode())
return true;

if (type->isTypeAlias())
return TraverseType(type->getAliasedType());

// Skip the template traversal if this occurrence of the template name is
// just a class qualifier for an out of line method, as opposed to an object
// instantiation, where the templated code would need to be inspected.
Expand Down Expand Up @@ -4219,7 +4222,7 @@ class IwyuAstConsumer

// If we're not in a forward-declare context, use of a template
// specialization requires having the full type information.
if (!CanForwardDeclareType(current_ast_node())) {
if (!CanForwardDeclareType(current_ast_node()) || type->isTypeAlias()) {
const TemplateInstantiationData data = GetTplInstData(type);
instantiated_template_visitor_.ScanInstantiatedType(
current_ast_node(), data.resugar_map, data.provided_types);
Expand Down
20 changes: 20 additions & 0 deletions tests/cxx/alias_template.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,26 @@ using AliasNested2 = FullUseTemplateArgInSizeof<FullUseTemplateArgInSizeof<T>>;
// IWYU: IndirectClass is...*indirect.h
AliasNested2<IndirectClass> aliasNested2;

template <typename T>
using UsingArgInternals = decltype(T::a);

// IWYU: IndirectClass needs a declaration
// IWYU: IndirectClass is...*indirect.h
UsingArgInternals<IndirectClass> aliased_int;
// Full type is needed even in fwd-decl context.
// IWYU: IndirectClass needs a declaration
// IWYU: IndirectClass is...*indirect.h
UsingArgInternals<IndirectClass>* p_int = nullptr;

template <typename T>
struct TplWithUsingArgInternals {
UsingArgInternals<T>* p = nullptr;
};

// IWYU: IndirectClass needs a declaration
// IWYU: IndirectClass is...*indirect.h
TplWithUsingArgInternals<IndirectClass> twuai;

/**** IWYU_SUMMARY
tests/cxx/alias_template.cc should add these lines:
Expand Down

0 comments on commit c6377ea

Please sign in to comment.