Bug 96593 - No "declaration changes meaning" diagnostic for alias templates
Summary: No "declaration changes meaning" diagnostic for alias templates
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 11.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
: 102444 (view as bug list)
Depends on:
Blocks:
 
Reported: 2020-08-12 17:48 UTC by Language Lawyer
Modified: 2021-09-22 09:14 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-08-18 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Language Lawyer 2020-08-12 17:48:06 UTC
"A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule."

The diagnostic for the rule is not required, but since GCC diagnoses some of the cases, there is a bugreport about missing diagnostic cases (bug 46983), and the check might become mandatory (will it?), I'd like file this bug.

GCC accepts the code with alias templates:

struct S {};

template <typename>
struct T {};

struct U
{
	template<typename>
	using S = S;

	template<typename>
	using T = T<void>;
};

but produces the "declaration changes meaning" error for type aliases.
GCC also diagnoses the case if the "outer" declaration is used before the corresponding alias template:

struct S {};

struct U
{
	S s;

	template<typename>
	using S = S; // error: declaration of ... changes meaning of 'S'
};

(From https://stackoverflow.com/q/63369264/)
Comment 1 Marek Polacek 2020-08-18 17:06:45 UTC
Like you say, this might be mandatory in C++23: https://wg21.link/p1697r0.  So confirmed.
Comment 2 gnzlbg 2021-09-22 09:13:21 UTC
*** Bug 102444 has been marked as a duplicate of this bug. ***
Comment 3 gnzlbg 2021-09-22 09:14:42 UTC
From 102444 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102444):

See http://eel.is/c++draft/class.member.lookup#6

  [class.member.lookup]/p6: "If it [the result of the search] differs from the result of a search in T for N from immediately after the class-specifier of T, the program is ill-formed, no diagnostic required."  A class definition is not allowed to change the meaning of a name that was already used earlier in the class definition.

While no diagnostic is required, I think a quality implementation like gcc should produce a diagnostic here and reject this program since it is ill-formed.

Example (found in the wild): https://gcc.godbolt.org/z/jhEj68Kq8

    struct plus {
      template<typename... Args>
      using invoke = void;
    };
    
    template <typename Fn, typename... Args>
    using invoke = typename Fn::template invoke<Args...>;
    
    template <typename Fn>
    struct compose
    {
      template <typename X, typename Y>
      using F = invoke<Fn, X, Y>;
    
      template <typename X>
      using invoke = invoke<Fn, X, X>;
    };
    
    using Q = compose<plus>::F<int, int>;

Is accepted by gcc.