File: compilers.rst

package info (click to toggle)
xtensor 0.25.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,476 kB
  • sloc: cpp: 65,302; makefile: 202; python: 171; javascript: 8
file content (139 lines) | stat: -rw-r--r-- 6,850 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht

   Distributed under the terms of the BSD 3-Clause License.

   The full license is in the file LICENSE, distributed with this software.

Compiler workarounds
====================

This page tracks the workarounds for the various compiler issues that we
encountered in the development. This is mostly of interest for developers
interested in contributing to xtensor.

Visual Studio 2015 and ``std::enable_if``
-----------------------------------------

With Visual Studio, ``std::enable_if`` evaluates its second argument, even if
the condition is false. This is the reason for the presence of the indirection
in the implementation of the ``xfunction_type_t`` meta-function.

Visual Studio 2017 and alias templates with non-class template parameters and multiple aliasing levels
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Alias template with non-class parameters only, and multiple levels of aliasing
are not properly considered as types by Visual Studio 2017. The base
``xcontainer`` template class underlying xtensor container types has such alias
templates defined. We avoid the multiple levels of aliasing in the case of Visual
Studio.

Visual Studio and ``min`` and ``max`` macros
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Visual Studio defines ``min`` and ``max`` macros causing calls to e.g.
``std::min`` and ``std::max`` to be interpreted as syntax errors. The
``NOMINMAX`` definition may be used to disable these macros.

In xtensor, to prevent macro replacements of ``min`` and ``max`` functions, we
wrap them with parentheses, so that client code does not need the ``NOMINMAX``
definition.

Visual Studio 2017 (15.7.1) seeing declarations as extra overloads
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In ``xvectorize.hpp``, Visual Studio 15.7.1 sees the forward declaration of ``vectorize(E&&)`` as a separate overload.

Visual Studio 2017 double non-class parameter pack expansion
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In ``xfixed.hpp`` we add a level of indirection to expand one parameter pack before the other.
Not doing this results in VS2017 complaining about a parameter pack that needs to be expanded in this
context while it actually is.

Visual Studio 2022 (19.31+) workaround inline compiler optimization bug
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In ``xstrides.hpp``, added an early return inside ``compute_strides`` when ``shape.size() == 0`` to
prevent a run time crash from occuring. Without this guard statement, instructions from inside the
for loop were somehow being reached, despite being logically unreachable.
Original issue  `here. <https://github.com/xtensor-stack/xtensor/issues/2568>`_
Upstream issue `here. <https://developercommunity.visualstudio.com/t/Runtime-Crash-msvc--1931-with-optimiz/10134617>`_

GCC-4.9 and Clang < 3.8 and constexpr ``std::min`` and ``std::max``
-------------------------------------------------------------------

``std::min`` and ``std::max`` are not constexpr in these compilers. In
``xio.hpp``, we locally define a ``XTENSOR_MIN`` macro used instead of
``std::min``. The macro is undefined right after it is used.

Clang < 3.8 not matching ``initializer_list`` with static arrays
----------------------------------------------------------------

Old versions of Clang don't handle overload resolution with braced initializer
lists correctly: braced initializer lists are not properly matched to static
arrays. This prevent compile-time detection of the length of a braced
initializer list.

A consequence is that we need to use stack-allocated shape types in these cases.
Workarounds for this compiler bug arise in various files of the code base.
Everywhere, the handling of `Clang < 3.8` is wrapped with checks for the
``X_OLD_CLANG`` macro.

**The support of `Clang < 4.0` is dropped in xtensor 0.22.**

Clang-cl and ``std::get``
-------------------------

`Clang-cl` does not allow to call ``std::get`` with ``*this`` as parameter from a class inheriting from std::tuple.
In that case, we explicitly upcast to ``std::tuple``.

GCC < 5.1 and ``std::is_trivially_default_constructible``
---------------------------------------------------------

The versions of the STL shipped with versions of GCC older than 5.1 are missing
a number of type traits, such as ``std::is_trivially_default_constructible``.
However, for some of them, equivalent type traits with different names are
provided, such as ``std::has_trivial_default_constructor``.

In this case, we polyfill the proper standard names using the deprecated
``std::has_trivial_default_constructor``. This must also be done when the
compiler is clang when it makes use of the GCC implementation of the STL,
which is the default behavior on linux. Properly detecting the version of the
GCC STL used by clang cannot be done with the ``__GNUC__``  macro, which is
overridden by clang. Instead, we check for the definition of the macro
``_GLIBCXX_USE_CXX11_ABI`` which is only defined with GCC versions greater than
``5``.

GCC-6 and the signature of ``std::isnan`` and ``std::isinf``
------------------------------------------------------------

We are not directly using ``std::isnan`` or ``std::isinf`` for the
implementation of ``xt::isnan`` and ``xt::isinf``, as a workaround to the
following bug in GCC-6 for the following reason.

- C++11 requires that the ``<cmath>`` header declares ``bool std::isnan(double)`` and ``bool std::isinf(double)``.
- C99 requires that the ``<math.h>`` header declares ``int ::isnan(double)`` and ``int ::isinf(double)``.

These two definitions would clash when importing both headers and using namespace std.

As of version 6, GCC detects whether the obsolete functions are present in the
C header ``<math.h>`` and uses them if they are, avoiding the clash. However,
this means that the function might return int instead of bool as C++11
requires, which is a bug.

GCC-8 and deleted functions
---------------------------

GCC-8 (8.2 specifically) doesn't seem to SFINAE deleted functions correctly. A
strided view on a dynamic_view errors with a message: use of deleted function.
It should pick the *other* implementation by SFINAE on the function
signature, because our ``has_strides<dynamic_view>`` meta-function should return
false. Instantiating the ``has_strides<dynamic_view>`` in the inner_types fixes the issue.
Original issue here: https://github.com/xtensor-stack/xtensor/issues/1273

Apple LLVM version >= 8.0.0
---------------------------

``tuple_cat`` is bugged and propagates the constness of its tuple arguments to the types
inside the tuple. When checking if the resulting tuple contains a given type, the const
qualified type also needs to be checked.