Title
Instantiation of variables with incomplete array types
Status
open
Section
13.9.2 [temp.inst]
Submitter
Richard Smith

Created on 2025-04-01.00:00:00 last changed 1 week ago

Messages

Date: 2026-02-24.22:24:11

Possible resolution:

Add a new paragraph after 13.9.2 [temp.inst] paragraph 8 as follows:

The existence of a definition of a variable or function is considered to affect the semantics of the program if the variable or function is needed for constant evaluation by an expression (7.7 [expr.const]), even if constant evaluation of the expression is not required or if constant expression evaluation does not use the definition. [ Example: ... ]

Similarly, the existence of a definition of a variable or function is considered to affect the semantics of the program in which an expression E appears if the instantiation changes the type of E, even if the variable or function is not odr-used (6.3 [basic.def.odr]). [ Example:

  template<typename T> struct X {
    static inline int arr[] = {1, 2, T::error};
  };
  decltype(+X<int>::arr) r;  // error: definition of X<int>::arr is instantiated, because its type changes from "array of unknown bound" to "array of 3 int"

-- end example ]

Date: 2025-04-01.00:00:00

(From submission #843.)

When a variable has an incomplete array type and a braceed initializer, the complete array type can be determined by instantiating a definition of the variable; see 13.9.2 [temp.inst] paragraph 4 and 13.9.2 [temp.inst] paragraph 7. The level of tracking differs between implementations.

  // Case 1: Clang rejects because the type of `*p` changes
  // between redeclarations; Clang seems to be incorrect:
  // The array bound affects the semantics of the program.
  template<typename T> struct X {
    static inline int arr[] = {1, 2, 3};
  };

  // Clang does not instantiate a definition here.
  extern decltype(X<int>::arr) *p;
  // Clang does instantiate a definition here.
  int n = sizeof(X<int>::arr);
  decltype(X<int>::arr) *p;

  // Case 2: GCC, EDG, MSVC reject because they instantiate a definition
  // of `X<int>::arr` even though it's not odr-used and doesn't appear to
  // affect the semantics of the program.
  template<typename T> struct X {
    static inline int arr[] = {1, 2, T::error};
  };

  // The array bound here doesn't matter; array-to-pointer decay doesn't
  // care about it.
  decltype(+X<int>::arr) r;
History
Date User Action Args
2026-02-24 22:24:11adminsetmessages: + msg8490
2025-04-01 00:00:00admincreate