Skip to content

key_selector: compile with clang and -fno-exceptions - #2913

Merged
lemire merged 1 commit into
masterfrom
fix-key-selector-no-exceptions
Oct 6, 2026
Merged

lemire merged 1 commit into
masterfrom
fix-key-selector-no-exceptions

Conversation

@lemire

@lemire lemire commented Oct 6, 2026

Copy link
Copy Markdown
Member

simdjson 5.0.2 does not compile with clang in C++20 mode when exceptions are disabled (-fno-exceptions), which is how Node.js and Chromium build:

simdjson.h:81978:5: error: cannot use 'throw' with exceptions disabled

The compile-time perfect-hash construction in key_selector.h reports failures with throw "..." inside consteval functions. Clang rejects any throw expression when exceptions are disabled, even one that is only evaluated at compile time. GCC accepts it.

Changes

  • key_selector.h: report the failures by calling a non-constexpr function instead of throwing. Reaching it during constant evaluation is still a compile-time error, and the diagnostic shows the call with its message (e.g. duplicate keys in for_each<"a", "a"> still fail to compile, with or without exceptions).
  • cmake/developer-options.cmake: compile the tests with -fno-exceptions when SIMDJSON_EXCEPTIONS=OFF.

Why CI did not catch it

In cmake/exception-flags.cmake, -fno-exceptions is only added when CMAKE_COMPILER_IS_GNUCC, only through target_link_libraries, and only to the library target. So the "CXX 20, noexcept" jobs (g++-13 and clang++-16) never compiled the headers without exceptions. With the CMake change alone, ondemand_object_find_field_tests fails to build on master with the error above.

I did not make the library itself build with -fno-exceptions: with libc++, std::string::__throw_length_error then calls abort(), which breaks the avoid_abort test.

Testing

AppleClang, -DSIMDJSON_CXX_STANDARD=20 -DSIMDJSON_EXCEPTIONS=OFF -DSIMDJSON_DEVELOPER_MODE=ON: everything builds, 109/109 tests pass. Node.js main also builds with simdjson 5.0.2 plus this patch.

The compile-time perfect-hash construction reported failures with
`throw "..."` inside consteval functions. Clang rejects any throw
expression when exceptions are disabled, even one that is only
evaluated at compile time, so simdjson.h no longer compiled under
C++20 with -fno-exceptions (as used by Node.js and Chromium). GCC
accepts it, which is why it went unnoticed.

Report the failures by calling a non-constexpr function instead: it
is still a compile-time error, with a diagnostic pointing at the
message, and it needs no exception support.

Also compile the tests with -fno-exceptions when SIMDJSON_EXCEPTIONS
is OFF. Until now, only GCC got the flag, and only on the library's
link line, so the "noexcept" CI jobs never compiled the headers
without exceptions.
@lemire lemire added the LGTM label Oct 6, 2026
@lemire
lemire merged commit e9cdb87 into master Oct 6, 2026
98 of 100 checks passed
@lemire
lemire deleted the fix-key-selector-no-exceptions branch October 6, 2026 23:24
nodejs-github-bot pushed a commit to nodejs/node that referenced this pull request Oct 11, 2026
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
nodejs-github-bot pushed a commit to nodejs/node that referenced this pull request Oct 11, 2026
env.h includes inspector_profiler.h, which included simdjson.h for
the types of two virtual methods and a parser member. As a result,
about 155 files in src/ parsed the amalgamated simdjson header,
which is over 10 MB.

Keep simdjson out of inspector_profiler.h: the profile connections
now say which field of `result` holds the profile, and
WriteProfile() takes the profile as raw JSON. The parser becomes a
local variable, so its buffers are no longer kept alive for the
lifetime of the Environment.

Also drop the unused include from node_task_runner.h, and let the
config file reader rewind its document instead of parsing the whole
file a second time with a second parser.

Now only the eight files that use simdjson include it. On an Apple
M-series machine, a clean rebuild of the src/ objects takes about
15% less CPU time (376 s to 320 s) and 19% less wall time at -j14.

Signed-off-by: Daniel Lemire <[email protected]>
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
richardlau pushed a commit to nodejs/node that referenced this pull request Oct 12, 2026
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
richardlau pushed a commit to nodejs/node that referenced this pull request Oct 12, 2026
env.h includes inspector_profiler.h, which included simdjson.h for
the types of two virtual methods and a parser member. As a result,
about 155 files in src/ parsed the amalgamated simdjson header,
which is over 10 MB.

Keep simdjson out of inspector_profiler.h: the profile connections
now say which field of `result` holds the profile, and
WriteProfile() takes the profile as raw JSON. The parser becomes a
local variable, so its buffers are no longer kept alive for the
lifetime of the Environment.

Also drop the unused include from node_task_runner.h, and let the
config file reader rewind its document instead of parsing the whole
file a second time with a second parser.

Now only the eight files that use simdjson include it. On an Apple
M-series machine, a clean rebuild of the src/ objects takes about
15% less CPU time (376 s to 320 s) and 19% less wall time at -j14.

Signed-off-by: Daniel Lemire <[email protected]>
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
richardlau pushed a commit to nodejs/node that referenced this pull request Oct 12, 2026
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
richardlau pushed a commit to nodejs/node that referenced this pull request Oct 12, 2026
env.h includes inspector_profiler.h, which included simdjson.h for
the types of two virtual methods and a parser member. As a result,
about 155 files in src/ parsed the amalgamated simdjson header,
which is over 10 MB.

Keep simdjson out of inspector_profiler.h: the profile connections
now say which field of `result` holds the profile, and
WriteProfile() takes the profile as raw JSON. The parser becomes a
local variable, so its buffers are no longer kept alive for the
lifetime of the Environment.

Also drop the unused include from node_task_runner.h, and let the
config file reader rewind its document instead of parsing the whole
file a second time with a second parser.

Now only the eight files that use simdjson include it. On an Apple
M-series machine, a clean rebuild of the src/ objects takes about
15% less CPU time (376 s to 320 s) and 19% less wall time at -j14.

Signed-off-by: Daniel Lemire <[email protected]>
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
richardlau pushed a commit to nodejs/node that referenced this pull request Oct 12, 2026
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
richardlau pushed a commit to nodejs/node that referenced this pull request Oct 12, 2026
env.h includes inspector_profiler.h, which included simdjson.h for
the types of two virtual methods and a parser member. As a result,
about 155 files in src/ parsed the amalgamated simdjson header,
which is over 10 MB.

Keep simdjson out of inspector_profiler.h: the profile connections
now say which field of `result` holds the profile, and
WriteProfile() takes the profile as raw JSON. The parser becomes a
local variable, so its buffers are no longer kept alive for the
lifetime of the Environment.

Also drop the unused include from node_task_runner.h, and let the
config file reader rewind its document instead of parsing the whole
file a second time with a second parser.

Now only the eight files that use simdjson include it. On an Apple
M-series machine, a clean rebuild of the src/ objects takes about
15% less CPU time (376 s to 320 s) and 19% less wall time at -j14.

Signed-off-by: Daniel Lemire <[email protected]>
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
aduh95 pushed a commit to nodejs/node that referenced this pull request Oct 23, 2026
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
aduh95 pushed a commit to nodejs/node that referenced this pull request Oct 28, 2026
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
aduh95 pushed a commit to nodejs/node that referenced this pull request Nov 11, 2026
PR-URL: #66620
Refs: simdjson/simdjson#2913
Refs: #66495
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant