This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[Moved to DR at the October, 2012 meeting.]
The current wording incorrectly appears to make the following example ill-formed:
constexpr const int &f(const int &n) { return n; } constexpr int k = f(0); // ill-formed
Proposed resolution (February, 2012):
Change 7.7 [expr.const] paragraph 2 as follows:
A conditional-expression is a core constant expression unless it involves one of the following...
...
an invocation of a constexpr function with arguments that, when substituted by function invocation substitution (9.2.6 [dcl.constexpr]), do not produce a core constant expression; [Example:...
an invocation of a constexpr constructor with arguments that, when substituted by function invocation substitution (9.2.6 [dcl.constexpr]), do not produce all core constant expressions for the constructor calls and full-expressions in the mem-initializers; [Example:...
...
an lvalue-to-rvalue conversion (7.3.2 [conv.lval]) unless it is applied to
...
a glvalue of literal type that refers to a non-volatile temporary object whose lifetime has not ended, initialized with a core constant expression;
...
an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization
, initialized with a constant expression;and either
it is initialized with a constant expression or
it is a non-static data member of a temporary object whose lifetime has not ended and is initialized with a core constant expression;
...
Change 7.7 [expr.const] paragraph 3 as follows, dividing it into two paragraphs:
A literal constant expression is a prvalue core constant expression of literal type, but not pointer type.An integral constant expression isa literal constantan expression of integral or unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression. [Note: Such expressions may be used as array bounds (9.3.4.5 [dcl.array], 7.6.2.8 [expr.new]), as bit-field lengths (11.4.10 [class.bit]), as enumerator initializers if the underlying type is not fixed (9.7.1 [dcl.enum]), as null pointer constants (7.3.12 [conv.ptr]), and as alignments (9.12.2 [dcl.align]). —end note] A converted constant expression of type T isa literal constantan expression, implicitly converted to a prvalue of type T, where theimplicit conversion (if any) is permitted in a literalconverted expression is a core constant expression and the implicit conversion sequence contains only user-defined conversions, lvalue-to-rvalue conversions (7.3.2 [conv.lval]), integral promotions (7.3.7 [conv.prom]), and integral conversions (7.3.9 [conv.integral]) other than narrowing conversions (9.4.5 [dcl.init.list]). [Note: such expressions may be used as case expressions (8.5.3 [stmt.switch]), as enumerator initializers if the underlying type is fixed (9.7.1 [dcl.enum]), and as integral or enumeration non-type template arguments (13.4 [temp.arg]). —end note]A literal constant expression is a prvalue core constant expression of literal type, but not pointer type (after conversions as required by the context). For a literal constant expression of array or class type, each subobject of its value shall have been initialized by a constant expression. A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function. An address constant expression is a prvalue core constant expression (after conversions as required by the context) of type std::nullptr_t or of pointer type that evaluates to the address of an object with static storage duration, to the address of a function, or to a null pointer value
, or a prvalue core constant expression of type std::nullptr_t. Collectively, literal constant expressions, reference constant expressions, and address constant expressions are called constant expressions.
Change the second example 9.2.6 [dcl.constexpr] paragraph 5 as follows:
constexpr int f(bool b) { return b ? throw 0 : 0; } // OK constexpr int f() {throw 0return f(true); } // ill-formed, no diagnostic required ...
This resolution also resolves issue 1455.