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

    <tr>
        <th>Summary</th>
        <td>
            Does clang define the behavior for an "array" manually created with a linker script?
        </td>
    </tr>

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

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

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

<pre>
    Hello, does clang, as extension, define in any way the interaction with the linker?

In particular, I have following program

~~~~
using test_signature = void();

void test2(){std::puts("test2");}

[[gnu::used]] constexpr test_signature* const t1 [[gnu::section(".tests")]] = +[]{std::puts("test1");};
[[gnu::used]] constexpr test_signature* const t2 [[gnu::section(".tests")]] = test2;
[[gnu::used]] constexpr test_signature* const t3 [[gnu::section(".tests")]] = test2;
// eventually many other

auto get_tests() noexcept {
  extern const test_signature* const tests_begin[];
  extern const test_signature* const tests_end[];
  return std::span<test_signature* const>(tests_begin, tests_end);
}

int main(){
  auto funcs = get_tests();
 for(const auto& v : funcs){
    v();
  }
}
~~~~


And following file linkerscript.ld

~~~~
SECTIONS
{
  .tests : {
    PROVIDE(tests_begin = .);
    KEEP(*(.tests))
 PROVIDE(tests_end = .);
  }
}
INSERT AFTER .text;
~~~~

And compile it with `clang --std=c++20 -Wl,-Tlinkerscript.ld main.cpp`.

The code seems to work, but strictly speaking, creating a span over tests_begin and tests_end is UB because no array has been declared in c++.

In c++23, one could change the code to

~~~~
auto get_tests() noexcept {
  extern const test_signature* const tests_begin[];
  extern const test_signature* const tests_end[];
 const auto tests_size = ((uintptr_t)(&tests_end) - (uintptr_t)(&tests_begin))/sizeof(test_signature*);
  auto begin = std::start_lifetime_as_array<test_signature* const>(tests_begin, tests_size);
  return std::span<test_signature* const>(begin, begin + tests_size);
}
~~~~

With the cast to uintptr_t to avoid UB for determining the size of the array, and then std::start_lifetime_as_array to begin the lifetime of the array over the area or memory one wants to iterate over.

The question is, in case one does not have yet `start_lifetime_as_array`, if this is necessary.

GCC recommends to use a generic inline-asm constraint: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107010, thus changing the code to

~~~~
auto get_tests() noexcept {
  extern const test_signature* const tests_begin[];
  extern const test_signature* const tests_end[];
  const auto tests_size = ((uintptr_t)(&tests_end) - (uintptr_t)
  test_signature** begin = tests_begin;
 asm("":"+r"(begin));
  return std::span<test_signature* const>(begin, begin + tests_size);
}
~~~~

this code compiles fine on clang too and also seems to work, but does it avoid UB too like in GCC?
And is the generic inline-asm constraint supported on all platforms that clang support? (ie are there any portability concerns when (cross-)compiling with clang on different architectures/platforms?)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzcV1uP4joS_jXmpQRKHGjggQcuzdnWSmdGMz07j8g4ReJtx87aDt3MQ__2VTnhOt2zUu9Iqz0SggS7yl_dPlcJ71VhEGdstGCjVU80obRutsMn5Xpbmx9mf0OtLeNLyC16kFqYgt6EB3wJaLyyJq7iThkEZUCYAzyLA4SSXgM6IYOyBp5VKOOfWpkndCxbs2TFknn7_WCgFi4o2WjhSOEDlGKPsLNa22dlCqidLZyoLoVeX19f26fG05aAPmzIIBEah8CyFeytyhmfMD5l2eJSlhaiAO-WxwsfcpbNWTavm-Djv7zbwDv58epSRfTZojBNK9V4zNloxUYrkNb4gC-1u4HE-Lxdg5DCjbjH6Kf23AHJ-e7gVidZw_iiDdT7aNMrtCeb_xuo_CNQW8_9lvOz33A-XzO-BtyjCY3Q-gAV5akNJbrLkIomWCgwbDqllBlgLL5IrAOwcacOYvI7c0T4HnJSstlioUwXtuwjCtDkP4k7DI0zcEoCXwvDsuU7ilh2z_jkEg5fXii_LI7rFFcmQCWUOdXI8fzoqF1jpI_evnHZGejOOsYnrTUkw_gd7IFl81b4WinA_lYezoCOD-eqv_yem_yCLHZKH4nGS6fqMND528zx9X75-PDpz6_HQ04Ht3kVoV5B_Pzl0z8eVjf-jE4YXCMH-Pv9_edo0JzxyTFPp_Rpt9yqQpO_pehnFzz8-fX-yyPM14_3XwjoSzhtv_UO-UXaqiaHqNCyMLtLIpFDvx8TaCWJWPiCJ9D_rhlf9h9vfBeTYCDrmt0lg0v1jyWCtDmCR6w8BAvP1j1Rem2bAD44JYM-gK9RPKn26pAORaAgCaCsBbtHd1kqIEx-Tk5QHr4tYItSNB7BWBDOiQOUwsMW0UCOUguHOd09nR2Dm5vlaF5Gx1tDiBudgyyFKTDeSdGEYN9Okf8XUjhXWbfHqx_Y3RsTxieNMqEObhNiEk4Yv7ukAOjDL_Z0rBGTl69Jsd11eXuF8TpzI5ZzgZzZKggXNlrtMKgKN8JvYlA_RGCE5frUj3DjSWmHli_eUf8uDX0_9jdSUJAsnFxJLyL2G98WRIiQY0BXKRN7lhIhxsnu4nPrCOqwqApKNP_Ra3DycdtdtctX-roai68owDqosLLuEIvhWZgQK1dRsxYwbv6pyP_VoI99nPKEjopNeIwKYmdobGg7tgMGIpj3QnyXRHECpzwVt0GJ3gt3uDryj-USHEpbVWjyiI6qX0CBBp2SoIxWBvvCV20UnVAmEFeXIdSe_BVv_ELKQWGagXUF4-ttU_xQWgvK4NI-b7ZNMZCFYtlaEQumyThJI7xQNr6lh2OI_hIE8fsZotP7Bg3ML-r-0qITGOGrtoGjD8WLM75w8WdyyTb_67qOeRrD312jHuKoY007DUGwNhar0N6-fQ3GAlHhTAIkotVTnJf-WC5Ps9C8ve8o4X6Z6OCburYuYE4whNZQaxF21tHZpQgdsm4Xy9YUOBWrn5Q7jFMarYmt0iocSLdEZzw8E-VQy-as933Gp63VVAexd2g1WwO52u3QoQkgnCxVQEnu94yvT1jILj7t5bMsn2ZT0cNZOuaTNB0lw2GvnMlsglMuhtscRzwd343H2-mUp3ycZNtxOhr21IwnfJgmySgZj8Z8OEg4pjJFnkmZTPhwyoYJVkLpgdb7ioq8p7xvcJamKR8mPS22qH2cbTnvRldOY66bkUB_2xSeDROtfPBnFUEFjbPVadw9zrYUlS2WYq-sizQuyFG8I2xOE0U7WsQGB_PWX6JrQ6HtpVi27jVOz25oSoWy2Q6krRhfE5Dup187-0-UgfF1NIy829m2n_F_BwAA__8VIPU9">