Skip to content

Commit 843ce7c

Browse files
authored
fixed #14265 - added column information to some simplecpp errors (danmar#7968)
1 parent fc69847 commit 843ce7c

File tree

6 files changed

+46
-49
lines changed

6 files changed

+46
-49
lines changed

lib/cppcheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
12221222

12231223
if (!hasValidConfig && currCfg == *configurations.rbegin()) {
12241224
// If there is no valid configuration then report error..
1225-
preprocessor.error(o.location.file(), o.location.line, o.msg, o.type);
1225+
preprocessor.error(o.location.file(), o.location.line, o.location.col, o.msg, o.type);
12261226
}
12271227
continue;
12281228

lib/preprocessor.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ Preprocessor::Preprocessor(simplecpp::TokenList& tokens, const Settings& setting
7070

7171
namespace {
7272
struct BadInlineSuppression {
73-
BadInlineSuppression(std::string file, const int line, std::string msg) : file(std::move(file)), line(line), errmsg(std::move(msg)) {}
73+
BadInlineSuppression(std::string file, const int line, unsigned int col, std::string msg) : file(std::move(file)), line(line), col(col), errmsg(std::move(msg)) {}
7474
std::string file;
75-
int line;
75+
int line; // TODO: needs to be unsigned
76+
unsigned int col;
7677
std::string errmsg;
7778
};
7879
}
@@ -137,7 +138,7 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std:
137138
}
138139

139140
if (!errmsg.empty())
140-
bad.emplace_back(tok->location.file(), tok->location.line, std::move(errmsg));
141+
bad.emplace_back(tok->location.file(), tok->location.line, tok->location.col, std::move(errmsg));
141142

142143
std::copy_if(suppressions.cbegin(), suppressions.cend(), std::back_inserter(inlineSuppressions), [](const SuppressionList::Suppression& s) {
143144
return !s.errorId.empty();
@@ -157,7 +158,7 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std:
157158
inlineSuppressions.push_back(std::move(s));
158159

159160
if (!errmsg.empty())
160-
bad.emplace_back(tok->location.file(), tok->location.line, std::move(errmsg));
161+
bad.emplace_back(tok->location.file(), tok->location.line, tok->location.col, std::move(errmsg));
161162
}
162163

163164
return true;
@@ -266,7 +267,7 @@ static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Sett
266267

267268
if (throwError) {
268269
// NOLINTNEXTLINE(bugprone-use-after-move) - moved only when thrownError is false
269-
bad.emplace_back(suppr.fileName, suppr.lineNumber, "Suppress End: No matching begin");
270+
bad.emplace_back(suppr.fileName, suppr.lineNumber, 0, "Suppress End: No matching begin"); // TODO: set column
270271
}
271272
} else if (SuppressionList::Type::unique == suppr.type || suppr.type == SuppressionList::Type::macro) {
272273
// special handling when suppressing { warnings for backwards compatibility
@@ -286,14 +287,14 @@ static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Sett
286287
if (onlyComments)
287288
suppressions.addSuppression(std::move(suppr)); // TODO: check result
288289
else
289-
bad.emplace_back(suppr.fileName, suppr.lineNumber, "File suppression should be at the top of the file");
290+
bad.emplace_back(suppr.fileName, suppr.lineNumber, 0, "File suppression should be at the top of the file"); // TODO: set column
290291
}
291292
}
292293
}
293294

294295
for (const SuppressionList::Suppression & suppr: inlineSuppressionsBlockBegin)
295296
// cppcheck-suppress useStlAlgorithm
296-
bad.emplace_back(suppr.fileName, suppr.lineNumber, "Suppress Begin: No matching end");
297+
bad.emplace_back(suppr.fileName, suppr.lineNumber, 0, "Suppress Begin: No matching end"); // TODO: set column
297298
}
298299

299300
void Preprocessor::inlineSuppressions(SuppressionList &suppressions)
@@ -306,7 +307,7 @@ void Preprocessor::inlineSuppressions(SuppressionList &suppressions)
306307
::addInlineSuppressions(filedata->tokens, mSettings, suppressions, err);
307308
}
308309
for (const BadInlineSuppression &bad : err) {
309-
error(bad.file, bad.line, bad.errmsg, simplecpp::Output::ERROR); // TODO: use individual (non-fatal) ID
310+
error(bad.file, bad.line, bad.col, bad.errmsg, simplecpp::Output::ERROR); // TODO: use individual (non-fatal) ID
310311
}
311312
}
312313

@@ -854,7 +855,7 @@ bool Preprocessor::reportOutput(const simplecpp::OutputList &outputList, bool sh
854855
case simplecpp::Output::ERROR:
855856
hasError = true;
856857
if (!startsWith(out.msg,"#error") || showerror)
857-
error(out.location.file(), out.location.line, out.msg, out.type);
858+
error(out.location.file(), out.location.line, out.location.col, out.msg, out.type);
858859
break;
859860
case simplecpp::Output::WARNING:
860861
case simplecpp::Output::PORTABILITY_BACKSLASH:
@@ -871,13 +872,13 @@ bool Preprocessor::reportOutput(const simplecpp::OutputList &outputList, bool sh
871872
case simplecpp::Output::SYNTAX_ERROR:
872873
case simplecpp::Output::UNHANDLED_CHAR_ERROR:
873874
hasError = true;
874-
error(out.location.file(), out.location.line, out.msg, out.type);
875+
error(out.location.file(), out.location.line, out.location.col, out.msg, out.type);
875876
break;
876877
case simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND:
877878
case simplecpp::Output::FILE_NOT_FOUND:
878879
case simplecpp::Output::DUI_ERROR:
879880
hasError = true;
880-
error("", 0, out.msg, out.type);
881+
error("", 0, 0, out.msg, out.type);
881882
break;
882883
}
883884
}
@@ -912,15 +913,15 @@ static std::string simplecppErrToId(simplecpp::Output::Type type)
912913
cppcheck::unreachable();
913914
}
914915

915-
void Preprocessor::error(const std::string &filename, unsigned int linenr, const std::string &msg, simplecpp::Output::Type type)
916+
void Preprocessor::error(const std::string &filename, unsigned int linenr, unsigned int col, const std::string &msg, simplecpp::Output::Type type)
916917
{
917918
std::list<ErrorMessage::FileLocation> locationList;
918919
if (!filename.empty()) {
919920
std::string file = Path::fromNativeSeparators(filename);
920921
if (mSettings.relativePaths)
921922
file = Path::getRelativePath(file, mSettings.basePaths);
922923

923-
locationList.emplace_back(file, linenr, 0); // TODO: set column
924+
locationList.emplace_back(file, linenr, col);
924925
}
925926
mErrorLogger.reportErr(ErrorMessage(std::move(locationList),
926927
mFile0,
@@ -956,11 +957,11 @@ void Preprocessor::getErrorMessages(ErrorLogger &errorLogger, const Settings &se
956957
Preprocessor preprocessor(tokens, settings, errorLogger, Standards::Language::CPP);
957958
preprocessor.missingInclude("", 1, 2, "", UserHeader);
958959
preprocessor.missingInclude("", 1, 2, "", SystemHeader);
959-
preprocessor.error("", 1, "message", simplecpp::Output::ERROR);
960-
preprocessor.error("", 1, "message", simplecpp::Output::SYNTAX_ERROR);
961-
preprocessor.error("", 1, "message", simplecpp::Output::UNHANDLED_CHAR_ERROR);
962-
preprocessor.error("", 1, "message", simplecpp::Output::INCLUDE_NESTED_TOO_DEEPLY);
963-
preprocessor.error("", 1, "message", simplecpp::Output::FILE_NOT_FOUND);
960+
preprocessor.error("", 1, 2, "message", simplecpp::Output::ERROR);
961+
preprocessor.error("", 1, 2, "message", simplecpp::Output::SYNTAX_ERROR);
962+
preprocessor.error("", 1, 2, "message", simplecpp::Output::UNHANDLED_CHAR_ERROR);
963+
preprocessor.error("", 1, 2, "message", simplecpp::Output::INCLUDE_NESTED_TOO_DEEPLY);
964+
preprocessor.error("", 1, 2, "message", simplecpp::Output::FILE_NOT_FOUND);
964965
}
965966

966967
void Preprocessor::dump(std::ostream &out) const

lib/preprocessor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
141141

142142
bool reportOutput(const simplecpp::OutputList &outputList, bool showerror);
143143

144-
void error(const std::string &filename, unsigned int linenr, const std::string &msg, simplecpp::Output::Type type);
144+
void error(const std::string &filename, unsigned int linenr, unsigned int col, const std::string &msg, simplecpp::Output::Type type);
145145

146146
private:
147147
static bool hasErrors(const simplecpp::Output &output);

lib/suppressions.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class CPPCHECKLIB SuppressionList {
5555
const std::string &getFileName() const {
5656
return mFileName;
5757
}
58-
int lineNumber;
58+
int lineNumber; // TODO: need to be unsigned
5959
Certainty certainty;
6060
std::string symbolNames;
6161
std::set<std::string> macroNames;
@@ -149,7 +149,7 @@ class CPPCHECKLIB SuppressionList {
149149
std::string errorId;
150150
std::string fileName;
151151
std::string extraComment;
152-
int lineNumber = NO_LINE;
152+
int lineNumber = NO_LINE; // TODO: needs to be unsigned
153153
int lineBegin = NO_LINE;
154154
int lineEnd = NO_LINE;
155155
Type type = Type::unique;

test/cli/other_test.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3429,8 +3429,7 @@ 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-
# TODO: lacks column information
3433-
'{}:2:0: error: #error "err" [preprocessorErrorDirective]'.format(test_file)
3432+
'{}:2:2: error: #error "err" [preprocessorErrorDirective]'.format(test_file)
34343433
]
34353434

34363435

@@ -3889,8 +3888,7 @@ def test_simplecpp_unhandled_char(tmp_path):
38893888
assert exitcode == 0, stdout
38903889
assert stdout.splitlines() == []
38913890
assert stderr.splitlines() == [
3892-
# TODO: lacks column information
3893-
'{}:2:0: error: The code contains unhandled character(s) (character code=228). Neither unicode nor extended ascii is supported. [unhandledChar]'.format(test_file)
3891+
'{}:2:5: error: The code contains unhandled character(s) (character code=228). Neither unicode nor extended ascii is supported. [unhandledChar]'.format(test_file)
38943892
]
38953893

38963894

@@ -3921,9 +3919,8 @@ def test_simplecpp_include_nested_too_deeply(tmp_path):
39213919
test_h = tmp_path / 'test_398.h'
39223920
assert stderr.splitlines() == [
39233921
# TODO: should only report the error once
3924-
# TODO: lacks column information
3925-
'{}:1:0: error: #include nested too deeply [includeNestedTooDeeply]'.format(test_h),
3926-
'{}:1:0: error: #include nested too deeply [includeNestedTooDeeply]'.format(test_h)
3922+
'{}:1:2: error: #include nested too deeply [includeNestedTooDeeply]'.format(test_h),
3923+
'{}:1:2: error: #include nested too deeply [includeNestedTooDeeply]'.format(test_h)
39273924
]
39283925

39293926

@@ -3944,9 +3941,8 @@ def test_simplecpp_syntax_error(tmp_path):
39443941
assert stdout.splitlines() == []
39453942
assert stderr.splitlines() == [
39463943
# TODO: should only report the error once
3947-
# TODO: lacks column information
3948-
'{}:1:0: error: No header in #include [syntaxError]'.format(test_file),
3949-
'{}:1:0: error: No header in #include [syntaxError]'.format(test_file)
3944+
'{}:1:2: error: No header in #include [syntaxError]'.format(test_file),
3945+
'{}:1:2: error: No header in #include [syntaxError]'.format(test_file)
39503946
]
39513947

39523948

test/testpreprocessor.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ class TestPreprocessor : public TestFixture {
437437
const auto settings = dinit(Settings, $.userDefines = "__cplusplus");
438438
const char code[] = "#error hello world!\n";
439439
(void)getcodeforcfg(settings, *this, code, "X", "test.c");
440-
ASSERT_EQUALS("[test.c:1:0]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str());
440+
ASSERT_EQUALS("[test.c:1:2]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str());
441441
}
442442

443443
// Ticket #2919 - wrong filename reported for #error
@@ -447,15 +447,15 @@ class TestPreprocessor : public TestFixture {
447447
const auto settings = dinit(Settings, $.userDefines = "TEST");
448448
const char code[] = "#file \"ab.h\"\n#error hello world!\n#endfile";
449449
(void)getcodeforcfg(settings, *this, code, "TEST", "test.c");
450-
ASSERT_EQUALS("[ab.h:1:0]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str());
450+
ASSERT_EQUALS("[ab.h:1:2]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str());
451451
}
452452

453453
// After including a file
454454
{
455455
const auto settings = dinit(Settings, $.userDefines = "TEST");
456456
const char code[] = "#file \"ab.h\"\n\n#endfile\n#error aaa";
457457
(void)getcodeforcfg(settings, *this, code, "TEST", "test.c");
458-
ASSERT_EQUALS("[test.c:2:0]: (error) #error aaa [preprocessorErrorDirective]\n", errout_str());
458+
ASSERT_EQUALS("[test.c:2:2]: (error) #error aaa [preprocessorErrorDirective]\n", errout_str());
459459
}
460460
}
461461

@@ -1529,7 +1529,7 @@ class TestPreprocessor : public TestFixture {
15291529
const std::map<std::string, std::string> actual = getcode(settings0, *this, filedata);
15301530

15311531
ASSERT_EQUALS(0, actual.size());
1532-
ASSERT_EQUALS("[file.c:2:0]: (error) No pair for character ('). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
1532+
ASSERT_EQUALS("[file.c:2:14]: (error) No pair for character ('). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
15331533
}
15341534
}
15351535

@@ -1544,7 +1544,7 @@ class TestPreprocessor : public TestFixture {
15441544
const std::string actual(expandMacros(filedata, *this));
15451545

15461546
ASSERT_EQUALS("", actual);
1547-
ASSERT_EQUALS("[file.cpp:3:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
1547+
ASSERT_EQUALS("[file.cpp:3:1]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
15481548
}
15491549

15501550
{
@@ -1557,7 +1557,7 @@ class TestPreprocessor : public TestFixture {
15571557
const std::string actual(expandMacros(filedata, *this));
15581558

15591559
ASSERT_EQUALS("", actual);
1560-
ASSERT_EQUALS("[abc.h:2:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
1560+
ASSERT_EQUALS("[abc.h:2:1]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
15611561
}
15621562

15631563
{
@@ -1570,7 +1570,7 @@ class TestPreprocessor : public TestFixture {
15701570
const std::string actual(expandMacros(filedata, *this));
15711571

15721572
ASSERT_EQUALS("", actual);
1573-
ASSERT_EQUALS("[file.cpp:2:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
1573+
ASSERT_EQUALS("[file.cpp:2:1]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
15741574
}
15751575

15761576
{
@@ -1582,7 +1582,7 @@ class TestPreprocessor : public TestFixture {
15821582
const std::string actual(expandMacros(filedata, *this));
15831583

15841584
ASSERT_EQUALS("", actual);
1585-
ASSERT_EQUALS("[file.cpp:2:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
1585+
ASSERT_EQUALS("[file.cpp:2:11]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
15861586
}
15871587

15881588
{
@@ -1598,7 +1598,7 @@ class TestPreprocessor : public TestFixture {
15981598
// expand macros..
15991599
(void)expandMacros(filedata, *this);
16001600

1601-
ASSERT_EQUALS("[file.cpp:7:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
1601+
ASSERT_EQUALS("[file.cpp:7:12]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
16021602
}
16031603
}
16041604

@@ -1651,7 +1651,7 @@ class TestPreprocessor : public TestFixture {
16511651
// Compare results..
16521652
ASSERT_EQUALS(1, actual.size());
16531653
ASSERT_EQUALS("", actual.at(""));
1654-
ASSERT_EQUALS("[file.c:6:0]: (error) failed to expand 'BC', Wrong number of parameters for macro 'BC'. [syntaxError]\n", errout_str());
1654+
ASSERT_EQUALS("[file.c:6:3]: (error) failed to expand 'BC', Wrong number of parameters for macro 'BC'. [syntaxError]\n", errout_str());
16551655
}
16561656

16571657
void newline_in_macro() {
@@ -1968,12 +1968,12 @@ class TestPreprocessor : public TestFixture {
19681968

19691969
void invalid_define_1() {
19701970
(void)getcode(settings0, *this, "#define =\n");
1971-
ASSERT_EQUALS("[file.c:1:0]: (error) Failed to parse #define [syntaxError]\n", errout_str());
1971+
ASSERT_EQUALS("[file.c:1:2]: (error) Failed to parse #define [syntaxError]\n", errout_str());
19721972
}
19731973

19741974
void invalid_define_2() { // #4036
19751975
(void)getcode(settings0, *this, "#define () {(int f(x) }\n");
1976-
ASSERT_EQUALS("[file.c:1:0]: (error) Failed to parse #define [syntaxError]\n", errout_str());
1976+
ASSERT_EQUALS("[file.c:1:2]: (error) Failed to parse #define [syntaxError]\n", errout_str());
19771977
}
19781978

19791979
void inline_suppressions() {
@@ -2119,7 +2119,7 @@ class TestPreprocessor : public TestFixture {
21192119
const char code[] = "#elif (){\n";
21202120
const std::string actual = getcodeforcfg(settings0, *this, code, "TEST", "test.c");
21212121
ASSERT_EQUALS("", actual);
2122-
ASSERT_EQUALS("[test.c:1:0]: (error) #elif without #if [syntaxError]\n", errout_str());
2122+
ASSERT_EQUALS("[test.c:1:2]: (error) #elif without #if [syntaxError]\n", errout_str());
21232123
}
21242124

21252125
void getConfigs1() {
@@ -2368,8 +2368,8 @@ class TestPreprocessor : public TestFixture {
23682368
// Preprocess => don't crash..
23692369
(void)getcode(settings0, *this, filedata);
23702370
ASSERT_EQUALS(
2371-
"[file.c:1:0]: (error) Syntax error in #ifdef [syntaxError]\n"
2372-
"[file.c:1:0]: (error) Syntax error in #ifdef [syntaxError]\n", errout_str());
2371+
"[file.c:1:2]: (error) Syntax error in #ifdef [syntaxError]\n"
2372+
"[file.c:1:2]: (error) Syntax error in #ifdef [syntaxError]\n", errout_str());
23732373
}
23742374

23752375
void garbage() {
@@ -2385,7 +2385,7 @@ class TestPreprocessor : public TestFixture {
23852385
const auto settings = dinit(Settings, $.userDefines = "foo");
23862386
const char code[] = "#error hello world!\n";
23872387
(void)getcodeforcfg(settings, *this, code, "X", "./././test.c");
2388-
ASSERT_EQUALS("[test.c:1:0]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str());
2388+
ASSERT_EQUALS("[test.c:1:2]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str());
23892389
}
23902390

23912391
// test for existing local include
@@ -2631,7 +2631,7 @@ class TestPreprocessor : public TestFixture {
26312631

26322632
settings.standards.setStd("c++11");
26332633
ASSERT_EQUALS("", getcodeforcfg(settings, *this, code, "", "test.cpp"));
2634-
ASSERT_EQUALS("[test.cpp:1:0]: (error) failed to evaluate #if condition, undefined function-like macro invocation: __has_include( ... ) [syntaxError]\n", errout_str()); // TODO: use individual ID
2634+
ASSERT_EQUALS("[test.cpp:1:2]: (error) failed to evaluate #if condition, undefined function-like macro invocation: __has_include( ... ) [syntaxError]\n", errout_str()); // TODO: use individual ID
26352635

26362636
settings.standards.setStd("c++17");
26372637
ASSERT_EQUALS("", getcodeforcfg(settings, *this, code, "", "test.cpp"));

0 commit comments

Comments
 (0)