Provide workaround for GCC Bug 66145
This commit is contained in:
parent
79ce6e9aa6
commit
980794066b
|
@ -23,6 +23,7 @@ set(HEADER_FILES
|
||||||
io/copy.h
|
io/copy.h
|
||||||
io/inifile.h
|
io/inifile.h
|
||||||
io/path.h
|
io/path.h
|
||||||
|
io/catchiofailure.h
|
||||||
math/math.h
|
math/math.h
|
||||||
misc/memory.h
|
misc/memory.h
|
||||||
misc/random.h
|
misc/random.h
|
||||||
|
@ -45,6 +46,7 @@ set(SRC_FILES
|
||||||
io/bitreader.cpp
|
io/bitreader.cpp
|
||||||
io/inifile.cpp
|
io/inifile.cpp
|
||||||
io/path.cpp
|
io/path.cpp
|
||||||
|
io/catchiofailure.cpp
|
||||||
math/math.cpp
|
math/math.cpp
|
||||||
misc/random.cpp
|
misc/random.cpp
|
||||||
tests/testutils.cpp
|
tests/testutils.cpp
|
||||||
|
|
|
@ -68,8 +68,8 @@ The repository [PKGBUILDs](https://github.com/Martchus/PKGBUILDs) contains files
|
||||||
PKGBUILD files to build for Windows using the Mingw-w64 compiler are also included.
|
PKGBUILD files to build for Windows using the Mingw-w64 compiler are also included.
|
||||||
|
|
||||||
### Notes
|
### Notes
|
||||||
* Because of [GCC Bug 66145](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145) usage of the new libstdc++ ABI
|
* There is a workaround for [GCC Bug 66145](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145) provided
|
||||||
is currently disabled. Linking against cppunit built using new libstdc++ ABI isn't possible.
|
in io/catchiofailure.h.
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
- remove unused features
|
- remove unused features
|
||||||
|
|
|
@ -43,8 +43,11 @@ configure_file(
|
||||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
|
||||||
# disable new ABI (can't catch ios_base::failure with new ABI)
|
# disable new ABI (can't catch ios_base::failure with new ABI)
|
||||||
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
|
set(FORCE_OLD_ABI "no" CACHE STRING "specifies whether usage of old ABI should be forced")
|
||||||
message(STATUS "Forcing usage of old CXX11 ABI to be able to catch std::ios_base::failure.")
|
if(${FORCE_OLD_ABI} STREQUAL "yes")
|
||||||
|
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
|
||||||
|
message(STATUS "Forcing usage of old CXX11 ABI.")
|
||||||
|
endif()
|
||||||
|
|
||||||
# enable debug-only code when doing a debug build
|
# enable debug-only code when doing a debug build
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
|
|
@ -137,7 +137,6 @@ string BinaryReader::readString(size_t length)
|
||||||
string BinaryReader::readTerminatedString(byte termination)
|
string BinaryReader::readTerminatedString(byte termination)
|
||||||
{
|
{
|
||||||
stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
|
stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
|
||||||
// thrown ios_base::failure when badbit or failbit is set
|
|
||||||
ss.exceptions(ios_base::badbit | ios_base::failbit);
|
ss.exceptions(ios_base::badbit | ios_base::failbit);
|
||||||
m_stream->get(*ss.rdbuf(), termination); // delim byte is not extracted from the stream
|
m_stream->get(*ss.rdbuf(), termination); // delim byte is not extracted from the stream
|
||||||
m_stream->seekg(1, ios_base::cur); // "extract" delim byte manually
|
m_stream->seekg(1, ios_base::cur); // "extract" delim byte manually
|
||||||
|
@ -175,7 +174,6 @@ string BinaryReader::readTerminatedString(size_t maxBytesToRead, byte terminatio
|
||||||
string BinaryReader::readMultibyteTerminatedStringBE(uint16 termination)
|
string BinaryReader::readMultibyteTerminatedStringBE(uint16 termination)
|
||||||
{
|
{
|
||||||
stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
|
stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
|
||||||
// thrown ios_base::failure when badbit or failbit is set
|
|
||||||
ss.exceptions(ios_base::badbit | ios_base::failbit);
|
ss.exceptions(ios_base::badbit | ios_base::failbit);
|
||||||
char *delimChars = m_buffer, *buff = m_buffer + 2;
|
char *delimChars = m_buffer, *buff = m_buffer + 2;
|
||||||
ConversionUtilities::BE::getBytes(termination, delimChars);
|
ConversionUtilities::BE::getBytes(termination, delimChars);
|
||||||
|
@ -196,7 +194,6 @@ string BinaryReader::readMultibyteTerminatedStringBE(uint16 termination)
|
||||||
string BinaryReader::readMultibyteTerminatedStringLE(uint16 termination)
|
string BinaryReader::readMultibyteTerminatedStringLE(uint16 termination)
|
||||||
{
|
{
|
||||||
stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
|
stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
|
||||||
// thrown ios_base::failure when badbit or failbit is set
|
|
||||||
ss.exceptions(ios_base::badbit | ios_base::failbit);
|
ss.exceptions(ios_base::badbit | ios_base::failbit);
|
||||||
char *delimChars = m_buffer, *buff = m_buffer + 2;
|
char *delimChars = m_buffer, *buff = m_buffer + 2;
|
||||||
ConversionUtilities::LE::getBytes(termination, delimChars);
|
ConversionUtilities::LE::getBytes(termination, delimChars);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "./bitreader.h"
|
#include "./bitreader.h"
|
||||||
|
#include "./catchiofailure.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ void BitReader::skipBits(std::size_t bitCount)
|
||||||
m_bitsAvail -= bitCount;
|
m_bitsAvail -= bitCount;
|
||||||
} else {
|
} else {
|
||||||
if((m_buffer += 1 + (bitCount -= m_bitsAvail) / 8) >= m_end) {
|
if((m_buffer += 1 + (bitCount -= m_bitsAvail) / 8) >= m_end) {
|
||||||
throw ios_base::failure("end of buffer exceeded");
|
throwIoFailure("end of buffer exceeded");
|
||||||
}
|
}
|
||||||
m_bitsAvail = 8 - (bitCount % 8);
|
m_bitsAvail = 8 - (bitCount % 8);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// ensure the old ABI is used
|
||||||
|
// TODO: add condition for GCC version if GCC Bug 66145 is fixed
|
||||||
|
#define _GLIBCXX_USE_CXX11_ABI 0
|
||||||
|
|
||||||
|
#include "./catchiofailure.h"
|
||||||
|
|
||||||
|
#include <ios>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace IoUtilities {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Provides a workaround for GCC Bug 66145.
|
||||||
|
* \returns Returns the error message.
|
||||||
|
* \throws Throws the current exception if it is not std::ios_base::failure.
|
||||||
|
*/
|
||||||
|
const char *catchIoFailure()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
throw;
|
||||||
|
} catch(const ios_base::failure &e) {
|
||||||
|
return e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Throws a std::ios_base::failure with the specified message.
|
||||||
|
*/
|
||||||
|
void throwIoFailure(const char *what)
|
||||||
|
{
|
||||||
|
throw ios_base::failure(what);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef IOUTILITIES_CATCHIOFAILURE_H
|
||||||
|
#define IOUTILITIES_CATCHIOFAILURE_H
|
||||||
|
|
||||||
|
#include "../application/global.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace IoUtilities {
|
||||||
|
|
||||||
|
LIB_EXPORT const char *catchIoFailure();
|
||||||
|
LIB_EXPORT void throwIoFailure(const char *what);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IOUTILITIES_CATCHIOFAILURE_H
|
|
@ -1,4 +1,5 @@
|
||||||
#include "./inifile.h"
|
#include "./inifile.h"
|
||||||
|
#include "./catchiofailure.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -135,13 +136,14 @@ void IniFile::parse(std::istream &inputStream)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const ios_base::failure &) {
|
} catch(...) {
|
||||||
|
const char *what = catchIoFailure();
|
||||||
if(inputStream.eof()) {
|
if(inputStream.eof()) {
|
||||||
// we just reached the end of the file
|
// we just reached the end of the file
|
||||||
// don't forget to save the last key/value pair
|
// don't forget to save the last key/value pair
|
||||||
finishKeyValue();
|
finishKeyValue();
|
||||||
} else {
|
} else {
|
||||||
throw;
|
throwIoFailure(what);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../io/path.h"
|
#include "../io/path.h"
|
||||||
#include "../io/inifile.h"
|
#include "../io/inifile.h"
|
||||||
#include "../io/copy.h"
|
#include "../io/copy.h"
|
||||||
|
#include "../io/catchiofailure.h"
|
||||||
|
|
||||||
#include <cppunit/extensions/HelperMacros.h>
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
#include <cppunit/TestFixture.h>
|
#include <cppunit/TestFixture.h>
|
||||||
|
@ -57,17 +58,27 @@ void IoTests::tearDown()
|
||||||
/*!
|
/*!
|
||||||
* \brief Tests for GCC Bug 66145.
|
* \brief Tests for GCC Bug 66145.
|
||||||
* \sa https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145
|
* \sa https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145
|
||||||
|
* \remarks Using workaround now; hence testing workaround instead.
|
||||||
*/
|
*/
|
||||||
void IoTests::testFailure()
|
void IoTests::testFailure()
|
||||||
{
|
{
|
||||||
fstream stream;
|
//fstream stream;
|
||||||
stream.exceptions(ios_base::failbit | ios_base::badbit);
|
//stream.exceptions(ios_base::failbit | ios_base::badbit);
|
||||||
CPPUNIT_ASSERT_THROW(stream.open("path/to/file/which/does/not/exist", ios_base::in), ios_base::failure);
|
//CPPUNIT_ASSERT_THROW(stream.open("path/to/file/which/does/not/exist", ios_base::in), ios_base::failure);
|
||||||
// check other exceptions used by my applications, too
|
// check other exceptions used by my applications, too
|
||||||
vector<int> testVec;
|
vector<int> testVec;
|
||||||
map<string, string> testMap;
|
map<string, string> testMap;
|
||||||
CPPUNIT_ASSERT_THROW(testVec.at(1), out_of_range);
|
CPPUNIT_ASSERT_THROW(testVec.at(1), out_of_range);
|
||||||
CPPUNIT_ASSERT_THROW(testMap.at("test"), out_of_range);
|
CPPUNIT_ASSERT_THROW(testMap.at("test"), out_of_range);
|
||||||
|
|
||||||
|
// check workaround
|
||||||
|
try {
|
||||||
|
fstream stream;
|
||||||
|
stream.exceptions(ios_base::failbit | ios_base::badbit);
|
||||||
|
stream.open("path/to/file/which/does/not/exist", ios_base::in);
|
||||||
|
} catch(...) {
|
||||||
|
catchIoFailure();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "../application/failure.h"
|
#include "../application/failure.h"
|
||||||
#include "../conversion/stringconversion.h"
|
#include "../conversion/stringconversion.h"
|
||||||
|
#include "../io/catchiofailure.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ApplicationUtilities;
|
using namespace ApplicationUtilities;
|
||||||
using namespace ConversionUtilities;
|
using namespace ConversionUtilities;
|
||||||
|
using namespace IoUtilities;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Contains classes and functions utilizing creating of test applications.
|
* \brief Contains classes and functions utilizing creating of test applications.
|
||||||
|
@ -193,7 +195,8 @@ string TestApplication::workingCopyPath(const string &name) const
|
||||||
workingCopy.open(path, ios_base::out | ios_base::binary | ios_base::trunc);
|
workingCopy.open(path, ios_base::out | ios_base::binary | ios_base::trunc);
|
||||||
workingCopy << origFile.rdbuf();
|
workingCopy << origFile.rdbuf();
|
||||||
return path;
|
return path;
|
||||||
} catch(const ios_base::failure &) {
|
} catch(...) {
|
||||||
|
catchIoFailure();
|
||||||
cerr << "Unable to create working copy for \"" << name << "\": an IO error occured." << endl;
|
cerr << "Unable to create working copy for \"" << name << "\": an IO error occured." << endl;
|
||||||
}
|
}
|
||||||
return string();
|
return string();
|
||||||
|
|
Loading…
Reference in New Issue