llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.06k stars 11.59k forks source link

Comparing pointer into string literal is not a constant expression #49380

Open davidstone opened 3 years ago

davidstone commented 3 years ago
Bugzilla Link 50036
Version trunk
OS Linux
CC @dwblaikie,@DougGregor,@zygoloid

Extended Description

The following well-formed translation unit

static_assert(+"a" != +"b");

is rejected by clang with the error message

<source>:1:20: error: static_assert expression is not an integral constant expression
static_assert(+"a" != +"b");
              ~~~~~^~~~~~~
1 error generated.
Compiler returned: 1

From the standard:

"An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following: ... a three-way comparison ([expr.spaceship]), relational ([expr.rel]), or equality ([expr.eq]) operator where the result is unspecified;" (http://eel.is/c++draft/expr.const#5.23)

And:

If at least one of the operands is a pointer, pointer conversions, function pointer conversions, and qualification conversions are performed on both operands to bring them to their composite pointer type. Comparing pointers is defined as follows:

(http://eel.is/c++draft/expr.eq#3)

The unspecified condition does not apply, so this should be accepted.

See it live: https://godbolt.org/z/vrWh54KM1

frederick-vs-ja commented 4 months ago

static_assert("abc" != "defg" + 1); needs to be accepted. However, it seems that static_assert("bcd" != "abcd" + 1); should be rejected. Perhaps we need to examine all possible overlapping ways of two string literal objects to detect whether the equality comparison has an unspecified result.

llvmbot commented 4 months ago

@llvm/issue-subscribers-clang-frontend

Author: David Stone (davidstone)

| | | | --- | --- | | Bugzilla Link | [50036](https://llvm.org/bz50036) | | Version | trunk | | OS | Linux | | CC | @dwblaikie,@DougGregor,@zygoloid | ## Extended Description The following well-formed translation unit ``` static_assert(+"a" != +"b"); ``` is rejected by clang with the error message ``` <source>:1:20: error: static_assert expression is not an integral constant expression static_assert(+"a" != +"b"); ~~~~~^~~~~~~ 1 error generated. Compiler returned: 1 ``` From the standard: "An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following: ... a three-way comparison ([expr.spaceship]), relational ([expr.rel]), or equality ([expr.eq]) operator where the result is unspecified;" (http://eel.is/c++draft/expr.const#5.23) And: If at least one of the operands is a pointer, pointer conversions, function pointer conversions, and qualification conversions are performed on both operands to bring them to their composite pointer type. Comparing pointers is defined as follows: - If one pointer represents the address of a complete object, and another pointer represents the address one past the last element of a different complete object,75 the result of the comparison is unspecified. - Otherwise, if the pointers are both null, both point to the same function, or both represent the same address, they compare equal. - Otherwise, the pointers compare unequal. (http://eel.is/c++draft/expr.eq#3) The unspecified condition does not apply, so this should be accepted. See it live: https://godbolt.org/z/vrWh54KM1