Skip to content

Use an inline constexpr for implicit inlining - #22

Merged
d-torrance merged 4 commits into
Macaulay2:masterfrom
d-torrance:cxx17-inline-constexpr
Aug 30, 2026
Merged

d-torrance merged 4 commits into
Macaulay2:masterfrom
d-torrance:cxx17-inline-constexpr

Conversation

@d-torrance

Copy link
Copy Markdown
Member

A follow-up to Macaulay2/mathic#25 and Macaulay2/mathicgb#62, though the
conclusion here is different.

memtailor is not vulnerable to the undefined-reference bug from those PRs
(Debian #1145665). That one needs a class-scope static const with an in-class
initializer, which is only a declaration and needs an out-of-line definition
once odr-used. memtailor has none. Its only two constants are at namespace
scope, where static const is a definition in every translation unit, so no
linker error is possible. Nothing here is broken today.

What the sweep did turn up:

Namespace-scope static means internal linkage, so every TU including
memtailor.h got its own private copy of MemoryAlignment and BitsPerByte.
The inline functions in MemoryBlocks.h name both, which is well defined only
thanks to the carve-out in [basic.def.odr] for const objects of literal type
holding the same value in every definition. inline constexpr makes each a
single entity and drops the reliance on that carve-out. Note that plain
constexpr would not have been enough: at namespace scope it implies const
and hence internal linkage, so inline is the part doing the work.

AX_CXX_COMPILE_STDCXX sat inside the AS_IF guarding the gtest checks, so
--without-gtest asked for no particular standard at all. The headers need
C++17 whether or not we build the unit tests. AC_LANG stays behind in the
gtest block, since AX_CXX_COMPILE_STDCXX does its own AC_LANG_PUSH([C++])
but AC_CHECK_HEADER([gtest/gtest.h]) does need the C++ compiler selected.

The #error guard then gives downstream users a clear diagnostic, which matters
now that the headers contain an inline variable.

Tested: make distcheck, and make check under both --with-gtest and
--without-gtest from a clean out-of-tree build; cmake builds with 26/26 tests
passing. Confirmed the guard fires at -std=c++14, and that under a forced
odr-use at -O0 nm now reports a single unique global symbol for each
constant rather than a per-TU local.

One caveat worth flagging: the toolchain I tested on has gtest 1.14, so these
runs are not evidence about gtest 1.18 specifically. The absence of class-scope
statics is the reason to expect memtailor is clear there, not the test runs.

Claude Opus 5 did the analysis and drafted the changes.

d-torrance and others added 4 commits August 29, 2026 20:14
AX_CXX_COMPILE_STDCXX was inside the AS_IF that guards the gtest checks,
so --without-gtest asked for no particular standard at all.  The library
headers need C++17 whether or not we build the unit tests, so run the
check unconditionally.

AC_LANG stays behind in the gtest block: AX_CXX_COMPILE_STDCXX does its
own AC_LANG_PUSH([C++]), but AC_CHECK_HEADER([gtest/gtest.h]) and the
AC_LINK_IFELSE that follows it do need the C++ compiler selected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
At namespace scope, static const gives internal linkage, so every
translation unit including memtailor.h got its own private copy of
MemoryAlignment and BitsPerByte.  The inline functions in MemoryBlocks.h
name both of them, which is only well defined thanks to the carve-out in
[basic.def.odr] for const objects of literal type that hold the same
value in every definition.

Since C++17, inline constexpr makes each of these a single entity across
the whole program, so we no longer lean on that carve-out.  Note that
plain constexpr would not have been enough: at namespace scope it
implies const and hence internal linkage, so inline is the part doing
the work here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both build systems ask for C++17, but that says nothing about how the
installed headers get compiled downstream.  They use an inline variable,
so give users of the library a clear diagnostic rather than whatever the
compiler makes of it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@d-torrance
d-torrance merged commit 948c8e5 into Macaulay2:master Aug 30, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant