Local typedefs in templates

Hi,

I have been working on fixing [1]. To me it is not obvious what is the
proper solution is. Maybe someone has an idea?

Consider this small test program:

template <class T>
void Function(T) {
  struct Struct {
    typedef int Something;
    Something x;
  };
}
void test() { Function('c'); }

Compiling it with -Wall -fsyntax-only generates the warning about the
local typedef being unused.

When adding -ast-dump one can see that there are two TypedefDecls, one
for the FunctionTemplateDecl and another for the one instantiation of
the template. The same thing applies when the typedef is dependent on a
template parameter, say "typedef T Something" in this case.

I observed this behaviour:

When the typedef is independent, then neither of the TypedefDecls will
be marked referenced as of now. Additionally, the type of ValueDecls
like "Something x;" has the non-templated typedef as its declaration.

When the typedef is dependent, then only the non-templated TypedefDecl
will be marked referenced. The type of ValueDecls does naturally refer
to the instantiated TypedefDecl.

Is it supposed to be that way?

If the types of declarations always referred to the instantiated
typedefs, it would be straightforward to fix by traversing all
declarations and marking the typedefs of their types referenced.

Alternatively, it would be possible to only check non-instantiated
types on being referenced. Actually, this might to be the simplest one..

Johannes

[1] https://bugs.llvm.org/show_bug.cgi?id=24883

Hi,

I have observed something slightly different - both the dependent and non-dependent non-instantiated TypedefDecl are marked as referenced (ToT clang). It seems to me that you could try fixing the issue by marking the instantiated TypedefDecls as referenced if the non-instantiated is referenced (see TemplateDeclInstantiator::InstantiateTypedefNameDecl).

Alex

I’m not entirely clear on where the warnings are/aren’t here, but some general advice:

Warnings should usually only be issued from either template patterns of template instantiations, not both. If the error can be detected in a pattern (either because it’s in a non-dependent expression, or the dependence of the expression doesn’t matter to the test) that’s better because you can warn exactly once no matter how many instantiations there are.

Otherwise, defer to the instantiations.