Skip to content
This repository was archived by the owner on Aug 5, 2022. It is now read-only.

Commit 67fd096

Browse files
committed
Merge pull request #310 from dawagner/optional-Werror-and-release-build
Add an option for removing Werror; have travis build in release config Fix some compilation errors in release configuration (strict aliasing violations) and add an option to enable/disable the -Werror flag. This is useful for integrators. Have travis build in release configuration instead of "None" configuration.
2 parents 658c286 + 21e45e2 commit 67fd096

File tree

8 files changed

+155
-26
lines changed

8 files changed

+155
-26
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ script:
5757
make -j &&
5858
CTEST_OUTPUT_ON_FAILURE=1 make ExperimentalTest ExperimentalMemCheck )
5959
- ( mkdir build && cd build &&
60-
cmake -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_INSTALL_PREFIX=../install .. &&
60+
cmake -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=Release .. &&
6161
make -j &&
6262
CTEST_OUTPUT_ON_FAILURE=1 make test &&
6363
make install &&
6464
cpack --verbose -G DEB && dpkg --info *.deb)
6565
- ( cd skeleton-subsystem &&
66-
cmake -DCMAKE_INSTALL_PREFIX=../install . &&
66+
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install . &&
6767
make &&
6868
CTEST_OUTPUT_ON_FAILURE=1 make ExperimentalTest ExperimentalMemCheck &&
6969
make install )

CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ option(DOXYGEN "Enable doxygen generation (you still have to run 'make doc')" OF
4242
option(REQUIREMENTS "Generate the html version of the 'requirements' documentation" OFF)
4343
option(PYTHON_BINDINGS "Python library to use the Parameter Framework from python" ON)
4444
option(C_BINDINGS "Library to use the Parameter Framework using a C API" ON)
45-
45+
option(FATAL_WARNINGS "Turn warnings into errors (-Werror flag)" ON)
4646

4747
# find and set the Parameter Framework's version
4848
execute_process(COMMAND git describe --tags --dirty
@@ -73,8 +73,14 @@ if(WIN32)
7373
# only public methods instead of the whole class, but they are too many to
7474
# do that. A separated plugin interface would fix that.
7575
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /FIiso646.h -wd4127 -wd4251")
76+
77+
# FIXME: Once we have removed all warnings on windows, add the /WX flags if
78+
# FATAL_WARNINGS is enabled
7679
else()
77-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -Wextra -Wconversion -Wno-sign-conversion")
80+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wconversion -Wno-sign-conversion")
81+
if(FATAL_WARNINGS)
82+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
83+
endif()
7884
endif()
7985

8086
# Hide symbols by default, then exposed symbols are the same in linux and windows

bindings/python/CMakeLists.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT REQUIRED)
5050
include_directories(${PYTHON_INCLUDE_DIRS})
5151

5252
set_property(SOURCE pfw.i PROPERTY CPLUSPLUS ON)
53-
set_property(SOURCE pfw.i PROPERTY SWIG_FLAGS "-Wall" "-Werror")
53+
set_property(SOURCE pfw.i PROPERTY SWIG_FLAGS "-Wall")
54+
if(FATAL_WARNINGS)
55+
set_property(SOURCE pfw.i APPEND PROPERTY SWIG_FLAGS "-Werror")
56+
endif()
5457

5558
swig_add_module(PyPfw python pfw.i)
5659
swig_link_libraries(PyPfw parameter ${PYTHON_LIBRARIES})
@@ -70,7 +73,8 @@ set_property(TARGET _PyPfw PROPERTY LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BIN
7073
# spurious anyway, as it relates to "ILogger *" which is an abstract
7174
# class/interface class and as such cannot be destroyed.
7275
# -Wno-error is set to prevent compilation failure in case of the code
73-
# generated by swig generates warnings
76+
# generated by swig generates warnings. We don't apply the FATAL_WARNING policy
77+
# here, since we consider this generated code as external.
7478
target_compile_definitions(_PyPfw PRIVATE SWIG_PYTHON_SILENT_MEMLEAK)
7579
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error")
7680

parameter/FloatingPointParameterType.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <climits>
3737
#include "convert.hpp"
3838
#include "Utility.h"
39+
#include "BinaryCopy.hpp"
3940

4041
using std::string;
4142

@@ -138,7 +139,7 @@ bool CFloatingPointParameterType::toBlackboard(
138139
return false;
139140
}
140141

141-
float fData = reinterpret_cast<const float &>(uiValue);
142+
auto fData = utility::binaryCopy<float>(uiValue);
142143

143144
// Check against NaN or infinity
144145
if (!std::isfinite(fData)) {
@@ -172,9 +173,7 @@ bool CFloatingPointParameterType::toBlackboard(
172173
}
173174

174175
// Move to the "raw memory" value space
175-
// Using an intermediary reference variable to avoid klocwork false positive
176-
const uint32_t &value = reinterpret_cast<const uint32_t &>(fValue);
177-
uiValue = value;
176+
uiValue = utility::binaryCopy<decltype(uiValue)>(fValue);
178177
return true;
179178
}
180179
}
@@ -193,8 +192,8 @@ void CFloatingPointParameterType::setOutOfRangeError(
193192
ostrStream << "real range [" << _fMin << ", " << _fMax << "]";
194193
} else {
195194

196-
uint32_t uiMin = reinterpret_cast<const uint32_t&>(_fMin);
197-
uint32_t uiMax = reinterpret_cast<const uint32_t&>(_fMax);
195+
auto uiMin = utility::binaryCopy<uint32_t>(_fMin);
196+
auto uiMax = utility::binaryCopy<uint32_t>(_fMax);
198197

199198
if (utility::isHexadecimal(strValue)) {
200199

@@ -228,7 +227,7 @@ bool CFloatingPointParameterType::fromBlackboard(
228227
} else {
229228

230229
// Move from "raw memory" value space to real space
231-
float fValue = reinterpret_cast<const float&>(uiValue);
230+
auto fValue = utility::binaryCopy<float>(uiValue);
232231

233232
ostrStream << fValue;
234233
}
@@ -252,9 +251,7 @@ bool CFloatingPointParameterType::toBlackboard(
252251

253252
// Cast is fine because dValue has been checked against the value range
254253
float fValue = static_cast<float>(dUserValue);
255-
// Using an intermediary reference variable to avoid klocwork false positive
256-
const uint32_t &value = reinterpret_cast<const uint32_t &>(fValue);
257-
uiValue = value;
254+
uiValue = utility::binaryCopy<decltype(uiValue)>(fValue);
258255
return true;
259256
}
260257

@@ -264,8 +261,7 @@ bool CFloatingPointParameterType::fromBlackboard(
264261
CParameterAccessContext& /*ctx*/) const
265262
{
266263
// Move from "raw memory" value space to real space
267-
// Using an intermediary reference variable to avoid klocwork false positive
268-
const float &fValue = reinterpret_cast<const float &>(uiValue);
264+
auto fValue = utility::binaryCopy<float>(uiValue);
269265

270266
dUserValue = fValue;
271267
return true;

test/functional-tests/FloatingPoint.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "ParameterFramework.hpp"
3333
#include "ElementHandle.hpp"
3434
#include "Test.hpp"
35+
#include "BinaryCopy.hpp"
3536

3637
#include <catch.hpp>
3738

@@ -114,12 +115,12 @@ SCENARIO_METHOD(FloatsPF, "Floating points", "[floating points]") {
114115
REQUIRE_NOTHROW(setRawValueSpace(true));
115116
for (auto &vec : Tests<string>{
116117
{ "(too high, as decimal)",
117-
std::to_string(reinterpret_cast<const uint32_t&>(tooHigh)) },
118+
std::to_string(::utility::binaryCopy<uint32_t>(tooHigh)) },
118119
{ "(too low, as decimal)",
119-
std::to_string(reinterpret_cast<const uint32_t&>(tooLow)) },
120+
std::to_string(::utility::binaryCopy<uint32_t>(tooLow)) },
120121
{ "(meaningless)", "foobar" },
121-
{ "(infinity)", std::to_string(reinterpret_cast<const uint32_t&>(inf))},
122-
{ "(NaN)", std::to_string(reinterpret_cast<const uint32_t&>(nan))},
122+
{ "(infinity)", std::to_string(::utility::binaryCopy<uint32_t>(inf))},
123+
{ "(NaN)", std::to_string(::utility::binaryCopy<uint32_t>(nan))},
123124
}) {
124125
GIVEN("Invalid value " + vec.title) {
125126
CHECK_THROWS_AS(setParameter(path, vec.payload), Exception);
@@ -130,11 +131,11 @@ SCENARIO_METHOD(FloatsPF, "Floating points", "[floating points]") {
130131
const float zero = 0.0f;
131132
for (auto &vec : Tests<string>{
132133
{ "(upper limit, as decimal)",
133-
std::to_string(reinterpret_cast<const uint32_t&>(upper)) },
134+
std::to_string(::utility::binaryCopy<uint32_t>(upper)) },
134135
{ "(lower limit, as decimal)",
135-
std::to_string(reinterpret_cast<const uint32_t&>(lower)) },
136+
std::to_string(::utility::binaryCopy<uint32_t>(lower)) },
136137
{ "(inside range, as decimal)",
137-
std::to_string(reinterpret_cast<const uint32_t&>(zero)) },
138+
std::to_string(::utility::binaryCopy<uint32_t>(zero)) },
138139
}) {
139140
GIVEN("A valid value " + vec.title) {
140141
CHECK_NOTHROW(setParameter(path, vec.payload));

test/functional-tests/Handle.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,10 @@ struct AllParamsPF : public ParameterFramework
162162
utility::TmpFile resultFile(result);
163163
utility::TmpFile expectedFile(expected);
164164
auto gitCommand = "git --no-pager diff --word-diff-regex='[^ <>]+' --color --no-index ";
165-
system((gitCommand + resultFile.getPath() + ' ' + expectedFile.getPath()).c_str());
165+
auto diffSuccess = system((gitCommand + resultFile.getPath() + ' ' + expectedFile.getPath()).c_str());
166+
if (diffSuccess != 0) {
167+
WARN("Failed to pretty-print the difference between actual and expected results.");
168+
}
166169
}
167170
}
168171

utility/BinaryCopy.hpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2015, Intel Corporation
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without modification,
6+
* are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation and/or
13+
* other materials provided with the distribution.
14+
*
15+
* 3. Neither the name of the copyright holder nor the names of its contributors
16+
* may be used to endorse or promote products derived from this software without
17+
* specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
#include <algorithm>
32+
#include <type_traits>
33+
#include "Iterator.hpp"
34+
#include <cassert>
35+
36+
namespace utility {
37+
38+
/**
39+
* Raw copy of one variable to another of the same size
40+
*
41+
* This can be regarder as a reinterpret_cast but does a copy and does not
42+
* break strict-aliasing rules.
43+
*
44+
* The source and the destination must have the same storage size (e.g. copying
45+
* a uint8_t into a uint32_t won't compile)
46+
*
47+
* @tparam Source The source type
48+
* @tparam Destination the destination type (even if it is a reference, this
49+
* function returns by copy)
50+
* @param source Source variable
51+
* @returns the source, reinterpreted as the destination type
52+
*/
53+
template <class Destination, class Source>
54+
typename std::remove_reference<Destination>::type binaryCopy(const Source source)
55+
{
56+
static_assert(sizeof(Source) == sizeof(Destination),
57+
"Source and Destination must have the same size");
58+
59+
using Destination_ = decltype(binaryCopy<Destination>(source));
60+
61+
union {
62+
Source source;
63+
Destination_ destination;
64+
} hack;
65+
66+
hack.source = source;
67+
return hack.destination;
68+
}
69+
70+
} // namespace utility

utility/test/utility.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*/
3030

3131
#include "Utility.h"
32+
#include "BinaryCopy.hpp"
3233

3334
#include <catch.hpp>
3435
#include <functional>
@@ -176,4 +177,52 @@ SCENARIO("isHexadecimal") {
176177
}
177178
}
178179

180+
template <class T1, class T2>
181+
void checkBinaryEqual(T1 v1, T2 v2) {
182+
// For some yet-unknown reason, GCC 4.8 complains about
183+
// CHECK(a == b);
184+
// and suggests that parentheses should be added. This is related to catch
185+
// internals but such construcuts have been used without problem in lots of
186+
// other places...
187+
// Besides, GCC 4.9 does not seem to have a problem with that either.
188+
// As a workaround, captures variables and parenthesize the expressions.
189+
190+
auto v2AsT1 = utility::binaryCopy<T1>(v2);
191+
CAPTURE(v1);
192+
CAPTURE(v2AsT1);
193+
CHECK((v1 == v2AsT1));
194+
195+
auto v1AsT2 = utility::binaryCopy<T2>(v1);
196+
CAPTURE(v2);
197+
CAPTURE(v1AsT2);
198+
CHECK((v2 == v1AsT2));
199+
}
200+
201+
SCENARIO("binaryCopy bit exactness") {
202+
GIVEN("Integer representations computed using http://babbage.cs.qc.cuny.edu/IEEE-754/") {
203+
204+
THEN("Floats should be coded on 32bits and fulfill IEEE-754."
205+
" That assumption is made in the Parameter Framework.") {
206+
REQUIRE(sizeof(float) == sizeof(uint32_t));
207+
REQUIRE(std::numeric_limits<float>::is_iec559);
208+
}
209+
WHEN("Testing float <=> uint32_t conversion") {
210+
checkBinaryEqual<float, uint32_t>(1.23456f, 0x3f9e0610);
211+
}
212+
213+
THEN("Doubles should be coded on 64bits and fulfill IEEE-754."
214+
" That assumption is made in the Parameter Framework.") {
215+
REQUIRE(sizeof(double) == sizeof(uint64_t));
216+
REQUIRE(std::numeric_limits<double>::is_iec559);
217+
}
218+
WHEN("Testing double <=> uint64_t conversion") {
219+
checkBinaryEqual<double, uint64_t>(987.65432109876, 0x408edd3c0cb3420e);
220+
}
221+
}
222+
223+
WHEN("Testing int8_t <=> uint8_t conversion") {
224+
checkBinaryEqual<int8_t, uint8_t>(-1, 0xff);
225+
}
226+
}
227+
179228
} // namespace utility

0 commit comments

Comments
 (0)