Skip to content

Commit 0aa5d5c

Browse files
committed
got rid of duplicated error reporting code in CppCheck::checkInternal() / cleanups
test/cli/other_test.py: added some tests for preprocessor errors
1 parent bb78bd8 commit 0aa5d5c

File tree

5 files changed

+113
-44
lines changed

5 files changed

+113
-44
lines changed

lib/cppcheck.cpp

Lines changed: 3 additions & 22 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

lib/preprocessor.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,11 @@ 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

148145
private:
146+
static bool hasErrors(const simplecpp::Output &output);
147+
149148
bool handleErrors(const simplecpp::OutputList &outputList, bool throwError);
150149

151150
static void simplifyPragmaAsmPrivate(simplecpp::TokenList &tokenList);

test/cli/other_test.py

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

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)