Skip to content

Commit b6282ef

Browse files
committed
Enable exceptions on ofstreams
1 parent a6b0129 commit b6282ef

File tree

8 files changed

+114
-50
lines changed

8 files changed

+114
-50
lines changed

cli/cppcheckexecutor.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#endif
4444

4545
#include <algorithm>
46+
#include <cassert>
4647
#include <cstdio>
4748
#include <cstdlib> // EXIT_SUCCESS and EXIT_FAILURE
4849
#include <functional>
@@ -75,7 +76,20 @@ CppCheckExecutor::CppCheckExecutor()
7576

7677
CppCheckExecutor::~CppCheckExecutor()
7778
{
78-
delete mErrorOutput;
79+
if (mErrorOutput) {
80+
try
81+
{
82+
mErrorOutput->close();
83+
}
84+
catch (const std::ios_base::failure&)
85+
{
86+
assert(false);
87+
88+
// TODO report error
89+
}
90+
91+
delete mErrorOutput;
92+
}
7993
}
8094

8195
bool CppCheckExecutor::parseFromArgs(Settings &settings, int argc, const char* const argv[])
@@ -266,7 +280,9 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
266280
mLatestProgressOutputTime = std::time(nullptr);
267281

268282
if (!settings.outputFile.empty()) {
269-
mErrorOutput = new std::ofstream(settings.outputFile);
283+
mErrorOutput = new std::ofstream();
284+
mErrorOutput->exceptions(std::ios_base::failbit | std::ios_base::badbit);
285+
mErrorOutput->open(settings.outputFile);
270286
}
271287

272288
if (settings.xml) {

gui/checkthread.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ static bool executeCommand(std::string exe, std::vector<std::string> args, std::
7676
output = process.readAllStandardOutput().toStdString();
7777

7878
if (redirect.compare(0,3,"2> ") == 0) {
79-
std::ofstream fout(redirect.substr(3));
79+
std::ofstream fout;
80+
fout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
81+
fout.open(redirect.substr(3));
8082
fout << process.readAllStandardError().toStdString();
8183
}
8284
return process.exitCode() == 0;

lib/analyzerinfo.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,28 @@
2323
#include "utils.h"
2424

2525
#include <tinyxml2.h>
26+
#include <cassert>
2627
#include <cstring>
2728
#include <map>
2829
#include <sstream> // IWYU pragma: keep
2930

31+
AnalyzerInformation::AnalyzerInformation()
32+
{
33+
mOutputStream.exceptions(std::ios_base::failbit | std::ios_base::badbit);
34+
}
35+
3036
AnalyzerInformation::~AnalyzerInformation()
3137
{
32-
close();
38+
try
39+
{
40+
close();
41+
}
42+
catch (const std::ios_base::failure&)
43+
{
44+
assert(false);
45+
46+
// TODO: Report error
47+
}
3348
}
3449

3550
static std::string getFilename(const std::string &fullpath)
@@ -49,7 +64,9 @@ void AnalyzerInformation::writeFilesTxt(const std::string &buildDir, const std::
4964
std::map<std::string, unsigned int> fileCount;
5065

5166
const std::string filesTxt(buildDir + "/files.txt");
52-
std::ofstream fout(filesTxt);
67+
std::ofstream fout;
68+
fout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
69+
fout.open(filesTxt);
5370
for (const std::string &f : sourcefiles) {
5471
const std::string afile = getFilename(f);
5572
fout << afile << ".a" << (++fileCount[afile]) << "::" << Path::simplifyPath(Path::fromNativeSeparators(f)) << '\n';
@@ -65,7 +82,6 @@ void AnalyzerInformation::writeFilesTxt(const std::string &buildDir, const std::
6582

6683
void AnalyzerInformation::close()
6784
{
68-
mAnalyzerInfoFile.clear();
6985
if (mOutputStream.is_open()) {
7086
mOutputStream << "</analyzerinfo>\n";
7187
mOutputStream.close();
@@ -139,12 +155,9 @@ bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::st
139155
return false;
140156

141157
mOutputStream.open(mAnalyzerInfoFile);
142-
if (mOutputStream.is_open()) {
143-
mOutputStream << "<?xml version=\"1.0\"?>\n";
144-
mOutputStream << "<analyzerinfo hash=\"" << hash << "\">\n";
145-
} else {
146-
mAnalyzerInfoFile.clear();
147-
}
158+
159+
mOutputStream << "<?xml version=\"1.0\"?>\n";
160+
mOutputStream << "<analyzerinfo hash=\"" << hash << "\">\n";
148161

149162
return true;
150163
}

lib/analyzerinfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class ErrorMessage;
4949
*/
5050
class CPPCHECKLIB AnalyzerInformation {
5151
public:
52+
AnalyzerInformation();
5253
~AnalyzerInformation();
5354

5455
static void writeFilesTxt(const std::string &buildDir, const std::list<std::string> &sourcefiles, const std::string &userDefines, const std::list<ImportProject::FileSettings> &fileSettings);

lib/cppcheck.cpp

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,16 @@ static void createDumpFile(const Settings& settings,
276276
dumpFile = getDumpFileName(settings, filename);
277277

278278
fdump.open(dumpFile);
279+
280+
// TODO: Technically, exceptions are allowed on the file so this is always false,
281+
// TODO: but the function is not aware of that as this function is not the owner of the file
279282
if (!fdump.is_open())
280283
return;
281284

282285
{
283-
std::ofstream fout(getCtuInfoFileName(dumpFile));
286+
std::ofstream fout;
287+
fout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
288+
fout.open(getCtuInfoFileName(dumpFile));
284289
}
285290

286291
std::string language;
@@ -396,7 +401,9 @@ CppCheck::CppCheck(ErrorLogger &errorLogger,
396401
, mTooManyConfigs(false)
397402
, mSimplify(true)
398403
, mExecuteCommand(std::move(executeCommand))
399-
{}
404+
{
405+
mPlistFile.exceptions(std::ios_base::failbit | std::ios_base::badbit);
406+
}
400407

401408
CppCheck::~CppCheck()
402409
{
@@ -408,7 +415,17 @@ CppCheck::~CppCheck()
408415

409416
if (mPlistFile.is_open()) {
410417
mPlistFile << ErrorLogger::plistFooter();
411-
mPlistFile.close();
418+
419+
try
420+
{
421+
mPlistFile.close();
422+
}
423+
catch (const std::ios_base::failure&)
424+
{
425+
assert(false);
426+
427+
// TODO report error
428+
}
412429
}
413430
}
414431

@@ -504,7 +521,9 @@ unsigned int CppCheck::check(const std::string &path)
504521
const std::string args2 = "-fsyntax-only -Xclang -ast-dump -fno-color-diagnostics " + flags + path;
505522
const std::string redirect2 = analyzerInfo.empty() ? std::string("2>&1") : ("2> " + clangStderr);
506523
if (!mSettings.buildDir.empty()) {
507-
std::ofstream fout(clangcmd);
524+
std::ofstream fout;
525+
fout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
526+
fout.open(clangcmd);
508527
fout << exe << " " << args2 << " " << redirect2 << std::endl;
509528
} else if (mSettings.verbose && !mSettings.quiet) {
510529
mErrorLogger.reportOut(exe + " " + args2);
@@ -535,7 +554,9 @@ unsigned int CppCheck::check(const std::string &path)
535554
}
536555

537556
if (!mSettings.buildDir.empty()) {
538-
std::ofstream fout(clangAst);
557+
std::ofstream fout;
558+
fout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
559+
fout.open(clangAst);
539560
fout << output2 << std::endl;
540561
}
541562

@@ -555,6 +576,7 @@ unsigned int CppCheck::check(const std::string &path)
555576

556577
// create dumpfile
557578
std::ofstream fdump;
579+
fdump.exceptions(std::ios_base::failbit | std::ios_base::badbit);
558580
std::string dumpFile;
559581
createDumpFile(mSettings, path, fdump, dumpFile);
560582
if (fdump.is_open()) {
@@ -716,9 +738,11 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
716738
filename2 = filename.substr(filename.rfind('/') + 1);
717739
else
718740
filename2 = filename;
741+
719742
const std::size_t fileNameHash = std::hash<std::string> {}(filename);
720743
filename2 = mSettings.plistOutput + filename2.substr(0, filename2.find('.')) + "_" + std::to_string(fileNameHash) + ".plist";
721744
mPlistFile.open(filename2);
745+
722746
mPlistFile << ErrorLogger::plistHeader(version(), files);
723747
}
724748

@@ -773,6 +797,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
773797

774798
// write dump file xml prolog
775799
std::ofstream fdump;
800+
fdump.exceptions(std::ios_base::failbit | std::ios_base::badbit);
776801
std::string dumpFile;
777802
createDumpFile(mSettings, filename, fdump, dumpFile);
778803
if (fdump.is_open()) {
@@ -1422,7 +1447,9 @@ void CppCheck::executeAddons(const std::vector<std::string>& files)
14221447

14231448
if (files.size() >= 2 || endsWith(files[0], ".ctu-info")) {
14241449
fileList = Path::getPathFromFilename(files[0]) + FILELIST;
1425-
std::ofstream fout(fileList);
1450+
std::ofstream fout;
1451+
fout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
1452+
fout.open(fileList);
14261453
for (const std::string& f: files)
14271454
fout << f << std::endl;
14281455
}
@@ -1681,7 +1708,10 @@ void CppCheck::analyseClangTidy(const ImportProject::FileSettings &fileSettings)
16811708

16821709
if (!mSettings.buildDir.empty()) {
16831710
const std::string analyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, fileSettings.filename, emptyString);
1684-
std::ofstream fcmd(analyzerInfoFile + ".clang-tidy-cmd");
1711+
1712+
std::ofstream fcmd;
1713+
fcmd.exceptions(std::ios_base::failbit | std::ios_base::badbit);
1714+
fcmd.open(analyzerInfoFile + ".clang-tidy-cmd");
16851715
fcmd << istr.str();
16861716
}
16871717

lib/summaries.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ std::string Summaries::create(const Tokenizer *tokenizer, const std::string &cfg
8686
const std::string::size_type pos = filename.rfind(".a");
8787
if (pos != std::string::npos) {
8888
filename[pos+1] = 's';
89-
std::ofstream fout(filename);
89+
std::ofstream fout;
90+
fout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
91+
fout.open(filename);
9092
fout << ostr.str();
9193
}
9294
}

test/helpers.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ ScopedFile::ScopedFile(std::string name, const std::string &content, std::string
5454
#endif
5555
}
5656

57-
std::ofstream of(mFullPath);
58-
if (!of.is_open())
59-
throw std::runtime_error("ScopedFile(" + mFullPath + ") - could not open file");
57+
std::ofstream of;
58+
of.exceptions(std::ios_base::failbit | std::ios_base::badbit);
59+
of.open(mFullPath);
6060
of << content;
6161
}
6262

tools/dmake.cpp

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <algorithm>
2222
#include <array>
23+
#include <cassert>
2324
#include <cstdlib>
2425
#include <fstream> // IWYU pragma: keep
2526
#include <functional>
@@ -214,8 +215,10 @@ static int write_vcxproj(const std::string &proj_name, const std::function<void(
214215
outstr.resize(pos+1, '\0');
215216
}
216217

218+
std::ofstream out;
219+
out.exceptions(std::ios_base::failbit | std::ios_base::badbit);
217220
// treat as binary to prevent implicit line ending conversions
218-
std::ofstream out(proj_name, std::ios::binary|std::ios::trunc);
221+
out.open(proj_name, std::ios::binary|std::ios::trunc);
219222
out << outstr;
220223

221224
return EXIT_SUCCESS;
@@ -394,36 +397,33 @@ int main(int argc, char **argv)
394397

395398
// QMAKE - lib/lib.pri
396399
{
397-
std::ofstream fout1("lib/lib.pri");
398-
if (fout1.is_open()) {
399-
fout1 << "# no manual edits - this file is autogenerated by dmake\n\n";
400-
fout1 << "include($$PWD/pcrerules.pri)\n";
401-
fout1 << "include($$PWD/../externals/externals.pri)\n";
402-
fout1 << "INCLUDEPATH += $$PWD\n";
403-
fout1 << "HEADERS += ";
404-
for (const std::string &libfile_h : libfiles_h) {
405-
fout1 << "$${PWD}/" << libfile_h;
406-
if (libfile_h != libfiles_h.back())
407-
fout1 << " \\\n" << std::string(11, ' ');
408-
}
409-
fout1 << "\n\nSOURCES += ";
410-
for (const std::string &libfile : libfiles) {
411-
fout1 << "$${PWD}/" << libfile.substr(4);
412-
if (libfile != libfiles.back())
413-
fout1 << " \\\n" << std::string(11, ' ');
414-
}
415-
fout1 << "\n";
400+
std::ofstream fout1;
401+
fout1.exceptions(std::ios_base::failbit | std::ios_base::badbit);
402+
fout1.open("lib/lib.pri");
403+
404+
fout1 << "# no manual edits - this file is autogenerated by dmake\n\n";
405+
fout1 << "include($$PWD/pcrerules.pri)\n";
406+
fout1 << "include($$PWD/../externals/externals.pri)\n";
407+
fout1 << "INCLUDEPATH += $$PWD\n";
408+
fout1 << "HEADERS += ";
409+
for (const std::string &libfile_h : libfiles_h) {
410+
fout1 << "$${PWD}/" << libfile_h;
411+
if (libfile_h != libfiles_h.back())
412+
fout1 << " \\\n" << std::string(11, ' ');
413+
}
414+
fout1 << "\n\nSOURCES += ";
415+
for (const std::string &libfile : libfiles) {
416+
fout1 << "$${PWD}/" << libfile.substr(4);
417+
if (libfile != libfiles.back())
418+
fout1 << " \\\n" << std::string(11, ' ');
416419
}
420+
fout1 << "\n";
417421
}
418422

419423
static const char makefile[] = "Makefile";
420-
std::ofstream fout(makefile, std::ios_base::trunc);
421-
if (!fout.is_open()) {
422-
std::cerr << "An error occurred while trying to open "
423-
<< makefile
424-
<< ".\n";
425-
return EXIT_FAILURE;
426-
}
424+
std::ofstream fout;
425+
fout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
426+
fout.open(makefile, std::ios_base::trunc);
427427

428428
fout << "# This file is generated by tools/dmake, do not edit.\n\n";
429429

0 commit comments

Comments
 (0)