Browse Source

Provide workaround for GCC Bug 66145

experiment/meta_header
Martchus 6 years ago
parent
commit
980794066b
  1. 2
      CMakeLists.txt
  2. 4
      README.md
  3. 7
      cmake/modules/BasicConfig.cmake
  4. 3
      io/binaryreader.cpp
  5. 3
      io/bitreader.cpp
  6. 36
      io/catchiofailure.cpp
  7. 15
      io/catchiofailure.h
  8. 6
      io/inifile.cpp
  9. 17
      tests/iotests.cpp
  10. 5
      tests/testutils.cpp

2
CMakeLists.txt

@ -23,6 +23,7 @@ set(HEADER_FILES
io/copy.h
io/inifile.h
io/path.h
io/catchiofailure.h
math/math.h
misc/memory.h
misc/random.h
@ -45,6 +46,7 @@ set(SRC_FILES
io/bitreader.cpp
io/inifile.cpp
io/path.cpp
io/catchiofailure.cpp
math/math.cpp
misc/random.cpp
tests/testutils.cpp

4
README.md

@ -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.
### Notes
* Because of [GCC Bug 66145](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145) usage of the new libstdc++ ABI
is currently disabled. Linking against cppunit built using new libstdc++ ABI isn't possible.
* There is a workaround for [GCC Bug 66145](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145) provided
in io/catchiofailure.h.
## TODO
- remove unused features

7
cmake/modules/BasicConfig.cmake

@ -43,8 +43,11 @@ configure_file(
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
# disable new ABI (can't catch ios_base::failure with new ABI)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
message(STATUS "Forcing usage of old CXX11 ABI to be able to catch std::ios_base::failure.")
set(FORCE_OLD_ABI "no" CACHE STRING "specifies whether usage of old ABI should be forced")
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
if(CMAKE_BUILD_TYPE STREQUAL "Debug")

3
io/binaryreader.cpp

@ -137,7 +137,6 @@ string BinaryReader::readString(size_t length)
string BinaryReader::readTerminatedString(byte termination)
{
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);
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
@ -175,7 +174,6 @@ string BinaryReader::readTerminatedString(size_t maxBytesToRead, byte terminatio
string BinaryReader::readMultibyteTerminatedStringBE(uint16 termination)
{
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);
char *delimChars = m_buffer, *buff = m_buffer + 2;
ConversionUtilities::BE::getBytes(termination, delimChars);
@ -196,7 +194,6 @@ string BinaryReader::readMultibyteTerminatedStringBE(uint16 termination)
string BinaryReader::readMultibyteTerminatedStringLE(uint16 termination)
{
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);
char *delimChars = m_buffer, *buff = m_buffer + 2;
ConversionUtilities::LE::getBytes(termination, delimChars);

3
io/bitreader.cpp

@ -1,4 +1,5 @@
#include "./bitreader.h"
#include "./catchiofailure.h"
using namespace std;
@ -21,7 +22,7 @@ void BitReader::skipBits(std::size_t bitCount)
m_bitsAvail -= bitCount;
} else {
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);
}

36
io/catchiofailure.cpp

@ -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);
}
}

15
io/catchiofailure.h

@ -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

6
io/inifile.cpp

@ -1,4 +1,5 @@
#include "./inifile.h"
#include "./catchiofailure.h"
#include <iostream>
@ -135,13 +136,14 @@ void IniFile::parse(std::istream &inputStream)
break;
}
}
} catch (const ios_base::failure &) {
} catch(...) {
const char *what = catchIoFailure();
if(inputStream.eof()) {
// we just reached the end of the file
// don't forget to save the last key/value pair
finishKeyValue();
} else {
throw;
throwIoFailure(what);
}
}
}

17
tests/iotests.cpp

@ -6,6 +6,7 @@
#include "../io/path.h"
#include "../io/inifile.h"
#include "../io/copy.h"
#include "../io/catchiofailure.h"
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestFixture.h>
@ -57,17 +58,27 @@ void IoTests::tearDown()
/*!
* \brief Tests for GCC Bug 66145.
* \sa https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145
* \remarks Using workaround now; hence testing workaround instead.
*/
void IoTests::testFailure()
{
fstream stream;
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);
//fstream stream;
//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);
// check other exceptions used by my applications, too
vector<int> testVec;
map<string, string> testMap;
CPPUNIT_ASSERT_THROW(testVec.at(1), 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();
}
}
/*!

5
tests/testutils.cpp

@ -2,6 +2,7 @@
#include "../application/failure.h"
#include "../conversion/stringconversion.h"
#include "../io/catchiofailure.h"
#include <cstdlib>
#include <cstring>
@ -13,6 +14,7 @@
using namespace std;
using namespace ApplicationUtilities;
using namespace ConversionUtilities;
using namespace IoUtilities;
/*!
* \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 << origFile.rdbuf();
return path;
} catch(const ios_base::failure &) {
} catch(...) {
catchIoFailure();
cerr << "Unable to create working copy for \"" << name << "\": an IO error occured." << endl;
}
return string();

Loading…
Cancel
Save