Skip to content

Commit 09edac0

Browse files
authored
got rid of duplicated error reporting code in CppCheck::checkInternal() / cleanups (#7960)
1 parent e21be4e commit 09edac0

File tree

7 files changed

+130
-63
lines changed

7 files changed

+130
-63
lines changed

lib/cppcheck.cpp

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -977,30 +977,11 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
977977
std::vector<std::string> files;
978978
simplecpp::TokenList tokens1 = createTokenList(files, &outputList);
979979

980-
// If there is a syntax error, report it and stop
981-
const auto output_it = std::find_if(outputList.cbegin(), outputList.cend(), [](const simplecpp::Output &output){
982-
return Preprocessor::hasErrors(output);
983-
});
984-
if (output_it != outputList.cend()) {
985-
const simplecpp::Output &output = *output_it;
986-
std::string locfile = Path::fromNativeSeparators(output.location.file());
987-
if (mSettings.relativePaths)
988-
locfile = Path::getRelativePath(locfile, mSettings.basePaths);
989-
990-
ErrorMessage::FileLocation loc1(locfile, output.location.line, output.location.col);
991-
992-
ErrorMessage errmsg({std::move(loc1)},
993-
"", // TODO: is this correct?
994-
Severity::error,
995-
output.msg,
996-
"syntaxError",
997-
Certainty::normal);
998-
mErrorLogger.reportErr(errmsg);
999-
return mLogger->exitcode();
1000-
}
1001-
1002980
Preprocessor preprocessor(tokens1, mSettings, mErrorLogger, file.lang());
1003981

982+
if (preprocessor.reportOutput(outputList, true))
983+
return mLogger->exitcode();
984+
1004985
if (!preprocessor.loadFiles(files))
1005986
return mLogger->exitcode();
1006987

@@ -1232,19 +1213,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
12321213

12331214
if (!hasValidConfig && currCfg == *configurations.rbegin()) {
12341215
// If there is no valid configuration then report error..
1235-
std::string locfile = Path::fromNativeSeparators(o.location.file());
1236-
if (mSettings.relativePaths)
1237-
locfile = Path::getRelativePath(locfile, mSettings.basePaths);
1238-
1239-
ErrorMessage::FileLocation loc1(locfile, o.location.line, o.location.col);
1240-
1241-
ErrorMessage errmsg({std::move(loc1)},
1242-
file.spath(),
1243-
Severity::error,
1244-
o.msg,
1245-
"preprocessorErrorDirective",
1246-
Certainty::normal);
1247-
mErrorLogger.reportErr(errmsg);
1216+
preprocessor.error(o.location.file(), o.location.line, o.msg);
12481217
}
12491218
continue;
12501219

lib/preprocessor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,7 @@ void Preprocessor::error(const std::string &filename, unsigned int linenr, const
899899
if (mSettings.relativePaths)
900900
file = Path::getRelativePath(file, mSettings.basePaths);
901901

902-
locationList.emplace_back(file, linenr, 0);
902+
locationList.emplace_back(file, linenr, 0); // TODO: set column
903903
}
904904
mErrorLogger.reportErr(ErrorMessage(std::move(locationList),
905905
mFile0,

lib/preprocessor.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,13 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
140140
*/
141141
void dump(std::ostream &out) const;
142142

143-
static bool hasErrors(const simplecpp::Output &output);
144-
145-
protected:
146143
bool reportOutput(const simplecpp::OutputList &outputList, bool showerror);
147144

145+
void error(const std::string &filename, unsigned int linenr, const std::string &msg);
146+
148147
private:
148+
static bool hasErrors(const simplecpp::Output &output);
149+
149150
bool handleErrors(const simplecpp::OutputList &outputList, bool throwError);
150151

151152
static void simplifyPragmaAsmPrivate(simplecpp::TokenList &tokenList);
@@ -159,7 +160,6 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
159160
};
160161

161162
void missingInclude(const std::string &filename, unsigned int linenr, unsigned int col, const std::string &header, HeaderTypes headerType);
162-
void error(const std::string &filename, unsigned int linenr, const std::string &msg);
163163

164164
void addRemarkComments(const simplecpp::TokenList &tokens, std::vector<RemarkComment> &remarkComments) const;
165165

@@ -173,7 +173,7 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
173173
simplecpp::FileDataCache mFileCache;
174174

175175
/** filename for cpp/c file - useful when reporting errors */
176-
std::string mFile0;
176+
std::string mFile0; // TODO: this is never set
177177
Standards::Language mLang{Standards::Language::None};
178178

179179
/** simplecpp tracking info */

test/cli/other_test.py

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3429,7 +3429,8 @@ def test_preprocess_enforced_cpp(tmp_path): # #10989
34293429
assert exitcode == 0, stdout if stdout else stderr
34303430
assert stdout.splitlines() == []
34313431
assert stderr.splitlines() == [
3432-
'{}:2:2: error: #error "err" [preprocessorErrorDirective]'.format(test_file)
3432+
# TODO: lacks column information
3433+
'{}:2:0: error: #error "err" [preprocessorErrorDirective]'.format(test_file)
34333434
]
34343435

34353436

@@ -3847,3 +3848,106 @@ def test_unmatched_file(tmp_path): # #14248 / #14249
38473848
f'{lib_file}:-1:0: information: Unmatched suppression: error6 [unmatchedSuppression]'
38483849
]
38493850
assert ret == 0, stdout
3851+
3852+
3853+
def test_simplecpp_warning(tmp_path):
3854+
test_file = tmp_path / 'test.c'
3855+
with open(test_file, "w") as f:
3856+
f.write(
3857+
"""
3858+
#define warning "warn msg"
3859+
""")
3860+
3861+
args = [
3862+
'-q',
3863+
'--template=simple',
3864+
str(test_file)
3865+
]
3866+
3867+
exitcode, stdout, stderr = cppcheck(args)
3868+
assert exitcode == 0, stdout
3869+
assert stdout.splitlines() == []
3870+
assert stderr.splitlines() == []
3871+
3872+
3873+
def test_simplecpp_unhandled_char(tmp_path):
3874+
test_file = tmp_path / 'test.c'
3875+
with open(test_file, "w", encoding='utf-8') as f:
3876+
f.write(
3877+
"""
3878+
int 你=0;
3879+
""")
3880+
3881+
args = [
3882+
'-q',
3883+
'--template=simple',
3884+
'--emit-duplicates',
3885+
str(test_file)
3886+
]
3887+
3888+
exitcode, stdout, stderr = cppcheck(args)
3889+
assert exitcode == 0, stdout
3890+
assert stdout.splitlines() == []
3891+
assert stderr.splitlines() == [
3892+
# TODO: lacks column information
3893+
# TODO: should report another ID
3894+
'{}:2:0: error: The code contains unhandled character(s) (character code=228). Neither unicode nor extended ascii is supported. [preprocessorErrorDirective]'.format(test_file)
3895+
]
3896+
3897+
3898+
def test_simplecpp_include_nested_too_deeply(tmp_path):
3899+
test_file = tmp_path / 'test.c'
3900+
with open(test_file, "w") as f:
3901+
f.write('#include "test.h"')
3902+
3903+
test_h = tmp_path / 'test.h'
3904+
with open(test_h, "w") as f:
3905+
f.write('#include "test_0.h"')
3906+
3907+
for i in range(400):
3908+
test_h = tmp_path / f'test_{i}.h'
3909+
with open(test_h, "w") as f:
3910+
f.write('#include "test_{}.h"'.format(i+1))
3911+
3912+
args = [
3913+
'-q',
3914+
'--template=simple',
3915+
'--emit-duplicates',
3916+
str(test_file)
3917+
]
3918+
3919+
exitcode, stdout, stderr = cppcheck(args)
3920+
assert exitcode == 0, stdout
3921+
assert stdout.splitlines() == []
3922+
test_h = tmp_path / 'test_398.h'
3923+
assert stderr.splitlines() == [
3924+
# TODO: should only report the error once
3925+
# TODO: should report another ID
3926+
# TODO: lacks column information
3927+
'{}:1:0: error: #include nested too deeply [preprocessorErrorDirective]'.format(test_h),
3928+
'{}:1:0: error: #include nested too deeply [preprocessorErrorDirective]'.format(test_h)
3929+
]
3930+
3931+
3932+
def test_simplecpp_syntax_error(tmp_path):
3933+
test_file = tmp_path / 'test.c'
3934+
with open(test_file, "w") as f:
3935+
f.write('#include ""')
3936+
3937+
args = [
3938+
'-q',
3939+
'--template=simple',
3940+
'--emit-duplicates',
3941+
str(test_file)
3942+
]
3943+
3944+
exitcode, stdout, stderr = cppcheck(args)
3945+
assert exitcode == 0, stdout
3946+
assert stdout.splitlines() == []
3947+
assert stderr.splitlines() == [
3948+
# TODO: should only report the error once
3949+
# TODO: should report another ID
3950+
# TODO: lacks column information
3951+
'{}:1:0: error: No header in #include [preprocessorErrorDirective]'.format(test_file),
3952+
'{}:1:0: error: No header in #include [preprocessorErrorDirective]'.format(test_file)
3953+
]

test/cli/project_test.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ def test_json_entry_file_not_found(tmpdir):
5959
with open(project_file, 'w') as f:
6060
f.write(json.dumps(compilation_db))
6161

62-
ret, _, stderr = cppcheck(["--project=" + str(project_file)])
62+
ret, _, stderr = cppcheck([
63+
'--template=simple',
64+
"--project=" + str(project_file)
65+
])
6366
assert 0 == ret
64-
assert f"{missing_file}:1:0: error: File is missing: {missing_file_posix} [syntaxError]\n\n^\n" == stderr
67+
assert stderr == f"nofile:0:0: error: File is missing: {missing_file_posix} [preprocessorErrorDirective]\n"
6568

6669

6770
def test_json_no_arguments(tmpdir):

test/testpreprocessor.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,12 @@ class TestPreprocessor : public TestFixture {
4949
TestPreprocessor() : TestFixture("TestPreprocessor") {}
5050

5151
private:
52-
class PreprocessorTest : public Preprocessor
53-
{
54-
friend class TestPreprocessor;
55-
public:
56-
PreprocessorTest(simplecpp::TokenList& tokens, const Settings& settings, ErrorLogger &errorLogger, Standards::Language lang)
57-
: Preprocessor(tokens, settings, errorLogger, lang)
58-
{}
59-
};
60-
6152
template<size_t size>
6253
std::string expandMacros(const char (&code)[size], ErrorLogger &errorLogger) const {
6354
simplecpp::OutputList outputList;
6455
std::vector<std::string> files;
6556
simplecpp::TokenList tokens1 = simplecpp::TokenList(code, files, "file.cpp", &outputList);
66-
PreprocessorTest p(tokens1, settingsDefault, errorLogger, Path::identify(tokens1.getFiles()[0], false));
57+
Preprocessor p(tokens1, settingsDefault, errorLogger, Path::identify(tokens1.getFiles()[0], false));
6758
simplecpp::TokenList tokens2 = p.preprocess("", files, true);
6859
(void)p.reportOutput(outputList, true);
6960
return tokens2.stringify();
@@ -128,7 +119,7 @@ class TestPreprocessor : public TestFixture {
128119

129120
simplecpp::TokenList tokens(code, size, files, Path::simplifyPath(filename), &outputList);
130121
// TODO: we should be using the actual Preprocessor implementation
131-
PreprocessorTest preprocessor(tokens, settings, errorlogger, Path::identify(tokens.getFiles()[0], false));
122+
Preprocessor preprocessor(tokens, settings, errorlogger, Path::identify(tokens.getFiles()[0], false));
132123

133124
// TODO: should be possible without a Preprocessor instance
134125
if (preprocessor.reportOutput(outputList, true))

test/testsuppressions.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ class TestSuppressions : public TestFixture {
8888
TEST_CASE(suppressingSyntaxErrorsFS); // #7076
8989
TEST_CASE(suppressingSyntaxErrorsInlineFiles); // #5917
9090
TEST_CASE(suppressingSyntaxErrorsInlineFS); // #5917
91-
TEST_CASE(suppressingSyntaxErrorsWhileFileReadFiles); // PR #1333
92-
TEST_CASE(suppressingSyntaxErrorsWhileFileReadFS); // PR #1333
91+
TEST_CASE(suppressingSimplecppErrorsWhileFileReadFiles); // PR #1333
92+
TEST_CASE(suppressingSimplecppErrorsWhileFileReadFS); // PR #1333
9393
TEST_CASE(symbol);
9494

9595
TEST_CASE(unusedFunctionFiles);
@@ -1341,7 +1341,7 @@ class TestSuppressions : public TestFixture {
13411341
suppressingSyntaxErrorsInlineInternal(&TestSuppressions::checkSuppressionFS);
13421342
}
13431343

1344-
void suppressingSyntaxErrorsWhileFileReadInternal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) { // syntaxError while file read should be suppressible (PR #1333)
1344+
void suppressingSimplecppErrorsWhileFileReadInternal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) { // syntaxError while file read should be suppressible (PR #1333)
13451345
const char code[] = "CONST (genType, KS_CONST) genService[KS_CFG_NR_OF_NVM_BLOCKS] =\n"
13461346
"{\n"
13471347
"[!VAR \"BC\" = \"$BC + 1\"!][!//\n"
@@ -1355,16 +1355,16 @@ class TestSuppressions : public TestFixture {
13551355
"[!VAR \"BC\" = \"$BC + 1\"!][!//\n"
13561356
"[!ENDIF!][!//\n"
13571357
"};";
1358-
ASSERT_EQUALS(0, (this->*check)(code, "syntaxError:test.cpp:4"));
1358+
ASSERT_EQUALS(0, (this->*check)(code, "preprocessorErrorDirective:test.cpp:4"));
13591359
ASSERT_EQUALS("", errout_str());
13601360
}
13611361

1362-
void suppressingSyntaxErrorsWhileFileReadFiles() {
1363-
suppressingSyntaxErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles);
1362+
void suppressingSimplecppErrorsWhileFileReadFiles() {
1363+
suppressingSimplecppErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles);
13641364
}
13651365

1366-
void suppressingSyntaxErrorsWhileFileReadFS() {
1367-
suppressingSyntaxErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles);
1366+
void suppressingSimplecppErrorsWhileFileReadFS() {
1367+
suppressingSimplecppErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles);
13681368
}
13691369

13701370
// TODO: this tests an internal function - should it be private?

0 commit comments

Comments
 (0)