|
3744 | 3744 | \end{note}
|
3745 | 3745 | \indextext{object lifetime|)}
|
3746 | 3746 |
|
3747 |
| -\rSec2[basic.indet]{Indeterminate values} |
| 3747 | +\rSec2[basic.indet]{Indeterminate and erroneous values} |
3748 | 3748 |
|
3749 | 3749 | \pnum
|
3750 | 3750 | \indextext{value!indeterminate}%
|
3751 | 3751 | \indextext{indeterminate value}%
|
3752 | 3752 | When storage for an object with automatic or dynamic storage duration
|
3753 |
| -is obtained, the object has an \defnadj{indeterminate}{value}, and if |
3754 |
| -no initialization is performed for the object, that object retains an |
3755 |
| -indeterminate value until that value is replaced\iref{expr.ass}. |
| 3753 | +is obtained, |
| 3754 | +the bytes comprising the storage for the object |
| 3755 | +have the following initial value: |
| 3756 | +\begin{itemize} |
| 3757 | +\item |
| 3758 | +If the object has dynamic storage duration, or |
| 3759 | +is the object associated with a variable or function parameter |
| 3760 | +whose first declaration is marked with |
| 3761 | +the \tcode{[[indeterminate]]} attribute\iref{dcl.attr.indet}, |
| 3762 | +the bytes have \defnadjx{indeterminate}{values}{value}; |
| 3763 | +\item |
| 3764 | +otherwise, the bytes have erroneous values, |
| 3765 | +where each value is determined by the implementation |
| 3766 | +independently of the state of the program. |
| 3767 | +\end{itemize} |
| 3768 | +If no initialization is performed for an object (including subobjects), |
| 3769 | +such a byte retains its initial value |
| 3770 | +until that value is replaced\iref{dcl.init.general,expr.ass}. |
| 3771 | +If any bit in the value representation has an indeterminate value, |
| 3772 | +the object has an indeterminate value; |
| 3773 | +otherwise, if any bit in the value representation has an erroneous value, |
| 3774 | +the object has an erroneous value\iref{conv.lval}. |
3756 | 3775 | \begin{note}
|
3757 | 3776 | Objects with static or thread storage duration are zero-initialized,
|
3758 | 3777 | see~\ref{basic.start.static}.
|
3759 | 3778 | \end{note}
|
3760 | 3779 |
|
3761 | 3780 | \pnum
|
3762 |
| -If an indeterminate value is produced by an evaluation, |
3763 |
| -the behavior is undefined except in the following cases: |
| 3781 | +Except in the following cases, |
| 3782 | +if an indeterminate value is produced by an evaluation, |
| 3783 | +the behavior is undefined, and |
| 3784 | +if an erroneous value is produced by an evaluation, |
| 3785 | +the behavior is erroneous and |
| 3786 | +the result of the evaluation is the value so produced but is not erroneous: |
3764 | 3787 | \begin{itemize}
|
3765 | 3788 | \item
|
3766 |
| - If an indeterminate value of |
| 3789 | + If an indeterminate or erroneous value of |
3767 | 3790 | unsigned ordinary character type\iref{basic.fundamental}
|
3768 | 3791 | or \tcode{std::byte} type\iref{cstddef.syn}
|
3769 | 3792 | is produced by the evaluation of:
|
|
3780 | 3803 | \item
|
3781 | 3804 | a discarded-value expression\iref{expr.context},
|
3782 | 3805 | \end{itemize}
|
3783 |
| - then the result of the operation is an indeterminate value. |
| 3806 | + then the result of the operation is an indeterminate value or |
| 3807 | + that errorneous value, respectively. |
3784 | 3808 | \item
|
3785 |
| - If an indeterminate value of |
| 3809 | + If an indeterminate or erroneous value of |
3786 | 3810 | unsigned ordinary character type or \tcode{std::byte} type
|
3787 | 3811 | is produced by the evaluation of
|
3788 | 3812 | the right operand of a simple assignment operator\iref{expr.ass}
|
3789 | 3813 | whose first operand is an lvalue of
|
3790 | 3814 | unsigned ordinary character type or \tcode{std::byte} type,
|
3791 |
| - an indeterminate value replaces |
| 3815 | + an indeterminate value or that erroneous value, respectively, replaces |
3792 | 3816 | the value of the object referred to by the left operand.
|
3793 | 3817 | \item
|
3794 |
| - If an indeterminate value of unsigned ordinary character type |
| 3818 | + If an indeterminate or erroneous value of unsigned ordinary character type |
3795 | 3819 | is produced by the evaluation of the initialization expression
|
3796 | 3820 | when initializing an object of unsigned ordinary character type,
|
3797 | 3821 | that object is initialized to an indeterminate
|
3798 |
| - value. |
| 3822 | + value or that erroneous value, respectively. |
3799 | 3823 | \item
|
3800 | 3824 | If an indeterminate value of
|
3801 | 3825 | unsigned ordinary character type or \tcode{std::byte} type
|
3802 | 3826 | is produced by the evaluation of the initialization expression
|
3803 | 3827 | when initializing an object of \tcode{std::byte} type,
|
3804 |
| - that object is initialized to an indeterminate value. |
| 3828 | + that object is initialized to an indeterminate value or |
| 3829 | + that erroneous value, respectively. |
3805 | 3830 | \end{itemize}
|
| 3831 | +Converting an indeterminate or erroneous value of |
| 3832 | +unsigned ordinary character type or \tcode{std::byte} type |
| 3833 | +produces an indeterminate or erroneous value, respectively. |
| 3834 | +In the latter case, |
| 3835 | +the result of the conversion is the value of the converted operand. |
3806 | 3836 | \begin{example}
|
3807 | 3837 | \begin{codeblock}
|
3808 | 3838 | int f(bool b) {
|
3809 |
| - unsigned char c; |
3810 |
| - unsigned char d = c; // OK, \tcode{d} has an indeterminate value |
| 3839 | + unsigned char *c = new unsigned char; |
| 3840 | + unsigned char d = *c; // OK, \tcode{d} has an indeterminate value |
3811 | 3841 | int e = d; // undefined behavior
|
3812 | 3842 | return b ? d : 0; // undefined behavior if \tcode{b} is \tcode{true}
|
3813 | 3843 | }
|
| 3844 | + |
| 3845 | +int g(bool b) { |
| 3846 | + unsigned char c; |
| 3847 | + unsigned char d = c; // no erroneous behavior, but \tcode{d} has an erroneous value |
| 3848 | + |
| 3849 | + assert(c == d); // holds, both integral promotions have erroneous behavior |
| 3850 | + |
| 3851 | + int e = d; // erroneous behavior |
| 3852 | + return b ? d : 0; // erroneous behavior if \tcode{b} is \tcode{true} |
| 3853 | +} |
| 3854 | + |
| 3855 | +void h() { |
| 3856 | + int d1, d2; |
| 3857 | + |
| 3858 | + int e1 = d1; // erroneous behavior |
| 3859 | + int e2 = d1; // erroneous behavior |
| 3860 | + |
| 3861 | + assert(e1 == e2); // holds |
| 3862 | + assert(e1 == d1); // holds, erroneous behavior |
| 3863 | + assert(e2 == d1); // holds, erroneous behavior |
| 3864 | + |
| 3865 | + std::memcpy(&d2, &d1, sizeof(int)); // no erroneous behavior, but \tcode{d2} has an erroneous value |
| 3866 | + assert(e1 == d2); // holds, erroneous behavior |
| 3867 | + assert(e2 == d2); // holds, erroneous behavior |
| 3868 | +} |
3814 | 3869 | \end{codeblock}
|
3815 | 3870 | \end{example}
|
3816 | 3871 |
|
|
0 commit comments