Skip to content

Unexpected reference to sugar type through constructor call in include-cleaner #60812

Closed
@kadircet

Description

@kadircet

a minimal repro looks like:

struct Foo { Foo(int); };
using Bar = Foo;
void bar(Bar);
void foo() {
  bar({3}); // Here we've a reference to Bar, not to Foo.
}

Despite things look like expected above, a real world scenario looks like:

// mytype.h
struct MyType { MyType(int); };

// container_base.h
template <typename T> struct ContainerBase {
  using ElementT = T;
};

// container.h
#include "container_base.h"
template <typename T> struct Container : public ContainerBase<T> {
void insert(const typename ContainerBase<T>::ElementT&);
};

// foo.cc
#include "container.h"
#include "mytype.h"

void foo() {
  Container<MyType> T;
  T.insert({42}); // Here we've got a reference to ElementT, not MyType.
}

In the real world example, it's completely unexpected (at least to me) that we need to depend on "container_base.h".
but unfortunately this goes both ways, there are certainly cases that look like first one, a more realistic example could be:

template <typename T> struct basic_string { basic_string (const T*); };
using string = basic_string<char>;
void foo(const string&);
void bar() {
   foo({nullptr}); // here i'd rather have a reference to string rather than basic_string.
}

So far attributing constructor calls to the sugared type seemed to be working in practice, but i think we'll definitely have more encounters with cases that look suspicious.

I can't see any heuristics with the current examples we have (hopefully we'll accumulate more soon), but one alternative without any heuristics could be to treat all constructor calls as ambiguous references to the sugar type.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions