Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is reading one-past-the-end pointer allowed in a constant expression when short-circuit disable its evaluation

Consider example:

template <char>
struct foo { };

int main() {
    foo<""[0]?""[1]:'\0'>{};
}

The code compiles in both [gcc] and [clang], but should it really? I know the expression ""[1] doesn't need to be evaluated as it was short-circuited. But standard isn't very clear if the expression can actually qualify as a core constant expression. Relevant [expr.const]/2 and especially part:

If e satisfies the constraints of a core constant expression, but evaluation of e would evaluate an operation that has undefined behavior as specified in [library] through [thread] of this document, it is unspecified whether e is a core constant expression.

raises my doubts...

like image 403
W.F. Avatar asked Jan 04 '23 03:01

W.F.


2 Answers

I believe the extract actually covers that:

If e satisfies the constraints of a core constant expression, but evaluation of e would evaluate an operation that has undefined behaviour as specified in [library] through [thread] of this document, it is unspecified whether e is a core constant expression.

There is actually no undefined behaviour in the expression ""[0]?""[1]:'\0' because the only problematic bit ""[1] is never actually executed. In fact, the entire expression can simply be optimised to '\0' without adverse effects.

The reason it's not executed comes from the standard itself (e.g., C++11 5.16 Conditional operator [expr.cond] /1:

Conditional expressions group right-to-left. The first expression is contextually converted to bool (Clause 4). It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression. Only one of the second and third expressions is evaluated.

Since ""[0] will always evaluate to false in the boolean context, the second sub-expression is never executed. It's really no conceptually different from the expression:

false ? (1/0) : 42

in that you'll never actually have to worry about the possibility of divide-by-zero.

like image 119
paxdiablo Avatar answered Jan 25 '23 22:01

paxdiablo


To answer that, one would have to quote the start of this paragraph, which says:

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:

And since the rules of the abstract machine promise the evaluation of the out of bounds access won't happen ([expr.cond]/1):

Conditional expressions group right-to-left. The first expression is contextually converted to bool. It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression. Only one of the second and third expressions is evaluated.

There's no undefined behavior, so it must be a core constant expression. Or at least, it's not the bullet you quoted which disqualifies it.

like image 45
StoryTeller - Unslander Monica Avatar answered Jan 26 '23 00:01

StoryTeller - Unslander Monica