Bug 79070 - Unhelpful error message for ambiguous type in template parameter
Summary: Unhelpful error message for ambiguous type in template parameter
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
: 97922 (view as bug list)
Depends on:
Blocks:
 
Reported: 2017-01-12 09:55 UTC by Björn Fahller
Modified: 2021-12-14 05:47 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-03-30 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Björn Fahller 2017-01-12 09:55:17 UTC
Compiling the below program with g++-7 on gcc.godbolt.org and other self builts, and also older releases of g++:

namespace A {
    class Foo {};
}
namespace B {
    class Foo{};
}

using namespace A;
using namespace B;

template <typename T> using t = T;
using type = t<Foo>;

//Foo* p = nullptr;

gives the unhelpful error message

maggot:/tmp>g++ -std=c++14 c.cpp
c.cpp:13:19: error: template argument 1 is invalid
 using type = t<Foo>;

Removing the comment for the Foo*, gives a considerably more helpful message:

maggot:/tmp>g++ -std=c++14 c.cpp
c.cpp:13:19: error: template argument 1 is invalid
 using type = t<Foo>;
                   ^
c.cpp:15:1: error: reference to 'Foo' is ambiguous
 Foo* p = nullptr;
 ^
c.cpp:6:11: note: candidates are: class B::Foo
     class Foo{};
           ^
c.cpp:3:11: note:                 class A::Foo
     class Foo {};
           ^
Comment 1 Björn Fahller 2017-01-12 10:19:53 UTC
More info: adding an alias for a function signature involving the ambiguous Foo in the above program gives a directly misleading error message:

using type = void(Foo);

c.cpp:12:18: error: expected ';' before '(' token
 using type = void(Foo);
                  ^
Comment 2 Martin Sebor 2017-02-08 23:11:40 UTC
Confirmed.
Comment 3 Barry Revzin 2021-03-29 22:44:56 UTC
Here are a few more cases, reduced from a larger example that took me a very long time to understand. I'm adding as comments the compile error emitted for each invalid use:

namespace N {
    template <typename T, typename U, typename V> struct Something { };
    template <typename> concept C = true;
    template <typename> struct X { };
}

using namespace N;
template <typename T> struct Something { };

// parse error in template argument list
static_assert(C<Something<int>>);

// template argument 1 is invalid
X<Something<int>> x;

// reference to Something is ambiguous
using T = Something<int>;

In the last case, the compiler error is super clear and it is obvious what the error is. In the other two, not so much.
Comment 4 Jonathan Wakely 2021-03-30 10:41:02 UTC
For Barry's example, Clang gives the exact same error in all three cases, which is much more useful:


79070.C:11:17: error: reference to 'Something' is ambiguous
static_assert(C<Something<int>>);
                ^
79070.C:8:30: note: candidate found by name lookup is 'Something'
template <typename T> struct Something { };
                             ^
79070.C:2:58: note: candidate found by name lookup is 'N::Something'
    template <typename T, typename U, typename V> struct Something { };
                                                         ^
79070.C:14:3: error: reference to 'Something' is ambiguous
X<Something<int>> x;
  ^
79070.C:8:30: note: candidate found by name lookup is 'Something'
template <typename T> struct Something { };
                             ^
79070.C:2:58: note: candidate found by name lookup is 'N::Something'
    template <typename T, typename U, typename V> struct Something { };
                                                         ^
79070.C:17:11: error: reference to 'Something' is ambiguous
using T = Something<int>;
          ^
79070.C:8:30: note: candidate found by name lookup is 'Something'
template <typename T> struct Something { };
                             ^
79070.C:2:58: note: candidate found by name lookup is 'N::Something'
    template <typename T, typename U, typename V> struct Something { };
                                                         ^
3 errors generated.
Comment 5 Andrew Pinski 2021-12-14 05:47:21 UTC
*** Bug 97922 has been marked as a duplicate of this bug. ***