<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/57957>57957</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            string literal storage optimization results in wrong-code
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          leni536
      </td>
    </tr>
</table>

<pre>
    clang++ 15.0.0
compiler options: `-std=c++20 -O2 -pedantic-errors`

Consider the following code (this has expected behavior):
```cpp
constexpr const char* ptr = "foo";
const char arr1[] = "foo";

bool foo() {
  return +arr1 == ptr; // returns true
}

bool bar() {
  return +arr2 == ptr; // returns false
}
```

So the string literal object referred by `ptr` overlaps with `arr1`. Unsurprisingly it can't overlap with `arr2` at the same time, since it would mean that `arr1` and `arr2` overlap, but that wouldn't be conforming.

However if similar array initialisations and pointer comparisons are done in different translation units then we can get contradictory behavior.

```cpp
// header.h
inline constexpr const char* ptr = "foo"

extern const char arr1[];
extern const char arr2[]; 

bool compare_arr1_to_ptr();
bool compare_arr2_to_ptr();

//arr1.cpp
const char arr1[] = "foo";
bool compare_arr1_to_ptr() {
  return +arr1 == ptr; // returns true
}

//arr2.cpp
const char arr2[] = "foo";
bool compare_arr2_to_ptr() {
  return +arr2 == ptr; // returns true
}

//main.cpp
#include <iostream>
int main() {
  std::cout << std::boolalpha << '\n';
  std::cout << compare_arr1_to_ptr() << '\n'; //true
  std::cout << compare_arr1_to_ptr() << '\n'; //true
  std::cout << (+arr1 == ptr) << '\n'; //false
  std::cout << (+arr2 == ptr) << '\n'; //false
  std::cout << (+arr1 == +arr2) << '\n'; //false
}
```
https://godbolt.org/z/7K8eqMqrf

None of the pointer comparisons in the program are unspecified as per [[expr.eq]](https://timsong-cpp.github.io/cppwp/n4868/expr.eq#3.1). 

It is tempting to apply the following wording in [[lex.string]](https://timsong-cpp.github.io/cppwp/n4868/lex.string#14.sentence-2):

> ...whether successive evaluations of a [string-literal](https://timsong-cpp.github.io/cppwp/n4868/lex.string#nt:string-literal) yield the same or a different object is unspecified[.](https://timsong-cpp.github.io/cppwp/n4868/lex.string#14.sentence-2)

But the string literal is evaluated exactly once, at the initialization of `ptr`. Further evaluations of `ptr` itself refers to the same object.

These out of the way, we have the following non-conforming behaviors of the executed program:
* `compare_arr1_to_ptr()` and `(+arr1 == ptr)` evaluate to different values. But `+arr1` either represents the same address of `ptr` or not. The pointers have the same values in the two evaluations. The same applies to the comparisons involving `arr2`.
* As both `compare_arr1_to_ptr()` and `compare_arr2_to_ptr()` evaluate to `true`, therefore `+arr1` represents the same address as `ptr`, and `ptr` represents the same address as `+arr2`. But `arr1` and `arr2` are distinct objects with disjoint bytes of storage [[basic.memobj]](https://timsong-cpp.github.io/cppwp/n4868/basic.memobj#intro.object-9.sentence-2).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy9V01v4zYU_DXyhbAg098HH_KxQYui7aHteUFJzzYXNKklqTjZX98hJVmyEycpdreAYscS33A4fHxvlJvyeVMooXcJv8XFJvM0S7Mku0-ym8IcKqnIMlN5abRLpjcsWWRj58tkel80ETxj4z85G1dUCu1lMSZrjXUY14A0n3cIlyWg_J7Y1ihljlLvWGFKYglf-b10bC8co6eKCk8ly2kvHqWxCV9j2hYKmPEqqqpjqJ1HjGXxP1bsBSJuWOUtA0VA860x-Eymt4OIOI4JayfJ_DaZ318Z23zmxigWn6xAhiXL9iljlnxtNQJvA1QACTiYGwi4-4CrHeOYtzW1qMv7F_B5oP0mPH8bfiuUe4HfyTWc7i8Tt8B5G_RX0pMVipn8C2QH2ha7F9R_DhsdplpkzDySVaJy7Cj9PtyPwi2ylP2jXW0rKx2w1DOTEFbohC99FzMM4QFL-GZ6cSDm5YESfscQXVAIPppalexAQmMQRvZTMaHLIUwLH6Lz2jejY3Qze04hH7bGHkAsHS7_F3MkxDK5xbQHqZo0EOCupZdCSSdiqscJKyM19GHhHAisMt63xEqjwVezUm6hF2kQsEI7FUNZDSQXVqnZkYIgbEc-8MGgUhbe2OdTdp9xe5ne7SbvSeDopPvmptRKamIfT_3BFPSE9Wj26iE4pf2rg_hpEHuRvY0-9Dlgffbmc8ibmM0nyMth_PVhw1UHsPT8oH_w2L7N6Ycf4BNdfo0u_090-cfovlMQ3qF7EFKngzyb4gyqOhTj6Z00qA4kDsn0U5dxnoWAl4xiJ7jBVRgcQ8Ti6m-GlQlV7UX3BIczmd-FM3pa_RWMN7bvFah28f2a_1fUCPEig94GHdTr91D5T0E9cW0n-Tjytf6y974KFqEJ2JkyN8qnxsJZPHzD3_K3FX39_avdDrPxj1BKzTY2hdfKrdTNI2t2Vhxi9a21g0eQW4k-BcdQISKer9tQDFP6GqoULr46J4RuA8TdGEmf7tCV6jyVOIcP-H1EI3nQs9UC2jx0KHw6TSdQJT2rd796Bqfi6QBHhP7pDRNVhdZ3bmuOxpbhG-wbaoqe0qblfie7ARCfTmapQ_chtM8xPzNKzef0E0vT9LgnsLPM1UVBzslHYvQoVN02OogvAssGddw6gh_GUXvEX2Aj1Z4lodWfrIBBnRy009aOQOnBZoNj-vOkG-h2W_vXPBLYtLoh8ehJFB77bgAQXEjrazoX8a2xAtD2ZKNS9lDbuBEX6vdGC76B1LZxYS7kVq9PFOTMLfy9J4cH4Noen6N4DkzgOeAt6CIjtdHj3hKd_IfrgumJijosrD1pfSrx6Pmvt_jenF2rg2FIp1xYVb_P4Sa5lAXFI8Bt5_dIRqksVZbCRrleC1GWuHchHRJIG5-yv_s64nodYlwzWVdR_NEMN6KJbPBxoCWd9D-vRo9GPQYBey-a9jrdOJabxu9-RK_rfuhCMPyOTSgodBdIIUMMKuG5ZG9phTp50iqma8OgFe_9yK5JhDRuN-uKM4_-WDpUx6I7x-2LA-5-CTuDlwtPcfscvLDYUVsjc-FkkR7ogKjvrJJnUMHbeGvShsx4fX7w0xFtJovFLJvx5XIyKjfTcj1di5GXXtHmogR0hMP78KE75JCpVj4m1tFGdnipHdVWbS46YkMYux6KkXrsvsY4coEZfkrnkKL4Z75cz5ej_Way4mKaLbPFbMuL-Txbr4vVusgKKlcrzmf5SImclNs0BnMkNzzjPFvz2WSVLSaTNF8u-ARD59t5RssFJbOM4ORUGiYOvXlkN5FDXu8cHuL9x7v-oUC72GmiDl_Ufm8QQVrOp4tRpLuJXP8FexgEFg">