Switch valptridx error style dispatching from using macro pasting to
using C++11 user-defined literals. This makes the code a bit easier to
read, and removes the need for a C99-conforming preprocessor here, which
should help anyone trying to port to Microsoft Visual Studio.
The new implementation also fixes a limitation of the previous
implementation. Before, an override that referenced an invalid name
could be silently ignored. Now, incorrect overrides cause an attempt to
use an undefined instantiation, which fails with a compilation error.
gcc considers strong_typedef to be POD both with and without the
explicit default. clang considers it to be POD only if the constructor
is explicitly defaulted.
For correctness, valptridx::ptridx instances must not be sliced down to
their component ::ptr or ::idx base classes. Previously, this was done
with a dummy template parameter to ensure that a bare ::idx had a
different type than the idx base of a ::ptridx. This extra distinction
complicates analysis of the code, and is not needed when the code is
already correct. Add the ability to build without slice checking.
Fix a bug where the ptridx converting move constructor delegated to the
ptr converting copy constructor, since the ptr copy constructor had
filename/line arguments, the ptr move constructor did not, and the
ptridx move constructor always passed filename/line.
For each link given as http://, verify that the site is accessible over
https:// and, if so, switch to it. These domains were converted:
* llvm.org
* clang.llvm.org
* en.cppreference.com
* www.dxx-rebirth.com
* www.libsdl.org
* www.scons.org
GCC std::remove_if overwrites removed elements using:
*dstiter = move(*srciter);
This is fine for normal containers, but produces incorrect results when
*dstiter returns a proxy object instead of a reference. In that case,
the proxy object is move-assigned from the source, then goes out of
scope. If the move assignment did not write to underlying storage, as
valptridx proxy objects do not, then incorrect results occur. This
broke ActiveDoor handling (fixed in 4a01fab66d98[1]) and has been a trap
waiting to recur. Apply reference-qualifiers to valptridx objects so
that move-assignment requires an lvalue for the left-hand side. This
permits normal use of move-assignment, but forces a compile error if
std::remove_if or similar are used on valptridx proxy objects.
[1]: 4a01fab66d
Various files included compiler-static_assert.h to use the compatibility
macros for compilers that lacked a working C++11 static_assert.
However, some source files used static_assert without this inclusion,
and no one ever reported problems. From this, assume that no one uses a
compiler which lacks C++11 static_assert. Remove the inclusions that
were only for the compatibility macro. Keep the inclusions that use the
assert_equal helper.
valptridx contains `static_assert` statements of the form:
static_assert(var.m, "");
where `var` is a non-`constexpr` reference and `m` is a `static
constexpr` member of a base type of `var`. gcc recognizes that a
`static constexpr` member is a constant expression and permits this.
clang rejects this, presumably because `var` is not a `constexpr`
variable. In the almost 3 years since this was added, clang has not
improved to permit this usage. Rather than continuing to suppress
static_assert in clang, rewrite this expression to be less clear, but be
compatible with clang.
Remove the `basic_` prefix from valptridx<T>::basic_ptr, ::basic_idx,
and ::basic_ptridx. Since the public names are typedef aliases of these
classes, these class names appear frequently in debug information and
error messages. The `basic_` prefix is unnecessary. Remove it.
git grep -lz '\<basic_\(ptr\|ptridx\|idx\)\>' -- common/include/ | xargs -0 sed -i -e 's/\<basic_\(ptr\|ptridx\|idx\)\>/\1/g'
Delete stub "compiler-type_traits.h" header. Redirect all uses to the
standard <type_traits> header.
git grep -wlz 'compiler-type_traits.h' -- '*.cpp' '*.h' | xargs -0 perl -p -i <<EOF
BEGIN {
$i = 0;
}
if (($i == 1 && $_ eq "\n") || ($i < 2 && /^#include "/)) {
# First blank line or first user-include after a system-include.
# Print, then never again for this file.
print "#include <type_traits>\n";
$i = 2;
} elsif ($i == 0) {
$i = 1 if (/^#include </);
} elsif ($_ eq "#include \"compiler-type_traits.h\"\n") {
# Remove this line if found.
$_ = '';
}
# Reset state machine when moving to next file.
$i = 0 if eof;
EOF
All supported compilers have an acceptable <type_traits>. Commit
4cb3d46148 ("Move <type_traits> test to Cxx11RequiredFeature") made
<type_traits> support mandatory in August and no one has objected.
Remove the indirection and use namespace std directly for type_traits
members.
Previously, valptridx used PREFIX for allow-invalid+mutable, c#PREFIX
for allow-invalid+const, v#PREFIX for require-valid+mutable, vc#PREFIX
for require-valid+const. Convert the types, factories, and all usage
sites to specify a qualifier for all four combinations:
im#PREFIX -> allow-invalid+mutable
ic#PREFIX -> allow-invalid+const
vm#PREFIX -> require-valid+mutable
vc#PREFIX -> require-valid+const
Changes to common/include/valptridx.h and common/include/fwd-valptridx.h
are manual. All other changes are generated by:
git grep -lz -e '\(obj\|seg\|clwall\|wall\|actdoor\|trg\)\(ptridx\|ptr\|idx\)\(_t\)\?\>' | xargs -0 sed -i -e 's/\<\(v\?\)\(\(obj\|seg\|clwall\|wall\|actdoor\|trg\)\(ptridx\|ptr\|idx\)\(_t\)\?\)\>/\1m\2/g'
for the 'm' prefix and:
git grep -lz -e '\(obj\|seg\|clwall\|wall\|actdoor\|trg\)\(ptridx\|ptr\|idx\)\(_t\)\?\>' | xargs -0 sed -i -e 's/\<\([cm]\(obj\|seg\|clwall\|wall\|actdoor\|trg\)\(ptridx\|ptr\|idx\)\(_t\)\?\)\>/i&/g'
for the 'i' prefix.
When using `gcc -fsanitize=undefined`, the compiler proves trivial
results, so `DXX_CONSTANT_TRUE` is defined. It then fails to prove that
`DXX_CONSTANT_TRUE(m_state == checked)` is false, causing a compile-time
error. Relax the check to occur only when it can prove `m_state` equal
to a disallowed value, rather than when it cannot prove `m_state` equal
to an allowed value.
Move the preprocessor guard so that the runtime check is always visible.
Optimizing compilers can still eliminate that check at compile-time when
it provably never fails.
By design, valptridx will throw an exception on invalid input. This is
better than silently permitting invalid input to corrupt program state.
Past releases blindly trusted that multiplayer peers would not send
invalid input. Conversion to the valptridx design eliminated the
undefined behavior when peers send invalid input, but still allowed
multiplayer peers to remotely crash the game by sending invalid inputs.
Add a mechanism to trap invalid inputs and gracefully ignore those
messages. This may cause game consistency issues, but will not allow
data corruption.
The declaration of valptridx_specialized_types needed to be found by
Argument Dependent Lookup, but this was inconvenient for some types.
Split the declaration of valptridx_specialized_types out from the
definition of valptridx global subtype.
Previously:
constexpr vTYPEptr{};
constexpr vcTYPEptr{};
Now:
__attribute_unused static vTYPEptr{};
constexpr vcTYPEptr{}; // unchanged from above
This is necessary for future work. It should have no user observable
effects for now.
Use a compound statement to cache the success condition as a local
boolean, then reference the local in the macro expansions. This should
hint to the optimizer that this is always the same expression, which
should encourage it not to repeat the test in the generated code.
Actual results vary. x86_64-pc-linux-gnu-g++-5.4.0 generates code that
is bigger, but uses fewer instructions.
Constructing valptridx::basic_ptr with a known-invalid magic index does
not require an array. Simplify the static_assert to reject uses of
factory functions with known-invalid magic index values. Fix the two
sites that fail with the stricter static_assert.
The segiter code used objptridx because end is signalled by object_none,
and vobjptridx does not allow object_none. However, the compiler
produces better code if segment_object_range_t returns vobjptridx and
future cleanups are easier if iterating objects_in yields vobjptridx
objects. Add a special-case override of the normal checking rules, move
the required checks into segiter, and then let segiter break the rules
normally enforced by valptridx. Add a comment explaining that this
permits unsafe coding and should be done only with a clear understanding
of the responsibilities it brings.