https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116909

            Bug ID: 116909
           Summary: Does g++ define the behavior for an "array" manually
                    created with a linker script?
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: federico at kircheis dot it
  Target Milestone: ---

Consider following program

main.cpp
----
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();
  }
}
----


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

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

The code works as expected (it calls the "registered functions" and prints
whatever is passed to std::puts), at least on linux, tested with different
optimizations flags (even with -flto and -fwhole-program), memory sanitizer and
valgrind.


I believe that the code triggers UB, because there is no array containing all
functions pointers, thus one is not allowed to do pointer arithmetic.

Since tests_begin and tests_end are created outside of C++, I guess there is
little for the compiler to do except assume that there is an array, and thus I
would like to claim that this code is portable between versions of gcc/ldd and
platforms (please correct me if I am wrong. any suggestion on how to improve it
or make more robust are welcome).

Assuming my linker script is correct, does g++ specify the behavior of the
program in this case?
If not, does it make sense to define it?
As the language does know nothing about "things" created outside of c++, it
cannot specify the behavior, but the toolchain should be able to do so.

I made the question for c++ with a c++ snippet, but the same question holds for
C too.

Reply via email to