https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98524

            Bug ID: 98524
           Summary: accepts-invalid instantiation of variable template
                    with different function pointer type from declaration
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: adr26__gcc at nunsway dot co.uk
  Target Milestone: ---

Consider:

  template<typename T> void (*TF)(int);
  template void (*TF<int>)(int);

Per [temp.explicit]/6, the above are two declarations of the same entity:

  The declaration in an explicit-instantiation and the declaration produced by
the corresponding substitution into the templated function, variable, or class
are two declarations of the same entity.

  [Note 1: These declarations are required to have matching types as specified
in [basic.link], except as specified in [except.spec].

  [Example 2:
    template<typename T> T var = {};
    template float var<float>;      // OK, instantiated variable has type float
    template int var<int[16]>[];    // OK, absence of major array bound is
permitted
    template int *var<int>;         // error: instantiated variable has type
int

    template<typename T> auto av = T();
    template int av<int>;           // OK, variable with type int can be
redeclared with type auto

    template<typename T> auto f() {}
    template void f<int>();         // error: function with deduced return type
                                    // redeclared with non-deduced return type
([dcl.spec.auto])

  — end example]
  — end note]

http://eel.is/c++draft/temp.explicit#6

and per [basic.link]/11.1, these two declarations of a entity which is a
variable shall declare the variable to be of the same (function pointer) type:

  For any two declarations of an entity E :

    (11.1) If one declares E to be a variable or function, the other shall
declare E as one of the same type.

http://eel.is/c++draft/basic.link#11.1

There isn't a "no diagnostic required" exception for this case in either
[temp.explicit] or [basic.link], and clang and ICC (EDG front end) both
correctly detect this error:

  clang:

  <source>:2:10: error: type 'void (*)(int)' of explicit instantiation of 'TF'
does not match expected type 'void (*)()'
  template void (*TF<int>)(int);
           ^
  <source>:1:29: note: variable template 'TF' declared here
  template<typename T> void (*TF)();
                              ^

  ICC:

  <source>(2): error: declaration is incompatible with "void (*TF)() [with
T=int]" (declared at line 1)
    template void (*TF<int>)(int);
                    ^

https://gcc.godbolt.org/z/qa6395

[NB: MSVC also incorrectly fails to detect this error, and I have reported this
in the context of a separate bug in its handling of variable templates:

https://developercommunity2.visualstudio.com/t/Incorrect-C3410-on-explicit-instantiatio/1301005

where it doesn't handle the correct code:

  template<typename T> void (*TF)(int);
  template void (*TF<int>)(int);

!]

g++ should issue a diagnostic for this, similarly to clang and ICC/EDG.

Thanks, Andrew R
  • [Bug c++/98524] New: accepts-... adr26__gcc at nunsway dot co.uk via Gcc-bugs

Reply via email to