Skip to content

Commit 615903c

Browse files
committed
Improve syntax errors for unmatched (){}[]
1 parent 32a5d66 commit 615903c

4 files changed

Lines changed: 48 additions & 29 deletions

File tree

lib/tokenize.cpp

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3188,10 +3188,10 @@ static void linkBrackets(const Tokenizer * const tokenizer, std::stack<const Tok
31883188
} else if (token->str()[0] == close) {
31893189
if (links.empty()) {
31903190
// Error, { and } don't match.
3191-
tokenizer->syntaxError(token, open);
3191+
tokenizer->unmatchedToken(token);
31923192
}
31933193
if (type.top()->str()[0] != open) {
3194-
tokenizer->syntaxError(type.top(), type.top()->str()[0]);
3194+
tokenizer->unmatchedToken(type.top());
31953195
}
31963196
type.pop();
31973197

@@ -3220,17 +3220,17 @@ void Tokenizer::createLinks()
32203220

32213221
if (!links1.empty()) {
32223222
// Error, { and } don't match.
3223-
syntaxError(links1.top(), '{');
3223+
unmatchedToken(links1.top());
32243224
}
32253225

32263226
if (!links2.empty()) {
32273227
// Error, ( and ) don't match.
3228-
syntaxError(links2.top(), '(');
3228+
unmatchedToken(links2.top());
32293229
}
32303230

32313231
if (!links3.empty()) {
32323232
// Error, [ and ] don't match.
3233-
syntaxError(links3.top(), '[');
3233+
unmatchedToken(links3.top());
32343234
}
32353235
}
32363236

@@ -7930,17 +7930,12 @@ void Tokenizer::syntaxError(const Token *tok) const
79307930
throw InternalError(tok, "syntax error", InternalError::SYNTAX);
79317931
}
79327932

7933-
void Tokenizer::syntaxError(const Token *tok, char c) const
7933+
void Tokenizer::unmatchedToken(const Token *tok) const
79347934
{
79357935
printDebugOutput(0);
7936-
if (mConfiguration.empty())
7937-
throw InternalError(tok,
7938-
std::string("Invalid number of character '") + c + "' when no macros are defined.",
7939-
InternalError::SYNTAX);
7940-
else
7941-
throw InternalError(tok,
7942-
std::string("Invalid number of character '") + c + "' when these macros are defined: '" + mConfiguration + "'.",
7943-
InternalError::SYNTAX);
7936+
throw InternalError(tok,
7937+
"Unmatched '" + tok->str() + "'. Configuration: '" + mConfiguration + "'.",
7938+
InternalError::SYNTAX);
79447939
}
79457940

79467941
void Tokenizer::syntaxErrorC(const Token *tok, const std::string &what) const

lib/tokenize.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,8 +594,8 @@ class CPPCHECKLIB Tokenizer {
594594
/** Syntax error */
595595
void syntaxError(const Token *tok) const;
596596

597-
/** Syntax error. Example: invalid number of ')' */
598-
void syntaxError(const Token *tok, char c) const;
597+
/** Syntax error. Unmatched character. */
598+
void unmatchedToken(const Token *tok) const;
599599

600600
/** Syntax error. C++ code in C file. */
601601
void syntaxErrorC(const Token *tok, const std::string &what) const;

samples/syntaxError/out.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[samples\syntaxError\bad.c:2]: (error) Invalid number of character '{' when no macros are defined.
1+
[samples\syntaxError\bad.c:2]: (error) Unmatched '{'. Configuration: ''.

test/testgarbage.cpp

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,19 @@ class TestGarbage : public TestFixture {
284284
return tokenizer.tokens()->stringifyList(false, false, false, true, false, 0, 0);
285285
}
286286

287+
std::string getSyntaxError(const char code[]) {
288+
Tokenizer tokenizer(&settings, this);
289+
std::istringstream istr(code);
290+
try {
291+
tokenizer.tokenize(istr, "test.cpp");
292+
} catch (InternalError& e) {
293+
if (e.id != "syntaxError")
294+
return "";
295+
return "[test.cpp:" + MathLib::toString(e.token->linenr()) + "] " + e.errorMessage;
296+
}
297+
return "";
298+
}
299+
287300
void wrong_syntax1() {
288301
{
289302
const char code[] ="TR(kvmpio, PROTO(int rw), ARGS(rw), TP_(aa->rw;))";
@@ -1007,23 +1020,34 @@ class TestGarbage : public TestFixture {
10071020
"}\n"), InternalError);
10081021

10091022
{
1010-
errout.str("");
10111023
const char code[] = "{\n"
1012-
" a(\n"
1024+
" a(\n" // <- error
10131025
"}\n"
10141026
"{\n"
10151027
" b());\n"
10161028
"}\n";
1017-
Tokenizer tokenizer(&settings, this);
1018-
std::istringstream istr(code);
1019-
try {
1020-
tokenizer.tokenize(istr, "test.cpp");
1021-
assertThrowFail(__FILE__, __LINE__);
1022-
} catch (InternalError& e) {
1023-
ASSERT_EQUALS("Invalid number of character '(' when no macros are defined.", e.errorMessage);
1024-
ASSERT_EQUALS("syntaxError", e.id);
1025-
ASSERT_EQUALS(2, e.token->linenr());
1026-
}
1029+
ASSERT_EQUALS("[test.cpp:2] Unmatched '('. Configuration: ''.", getSyntaxError(code));
1030+
}
1031+
1032+
{
1033+
const char code[] = "void f() {\n"
1034+
" int x = 3) + 0;\n" // <- error: unmatched )
1035+
"}\n";
1036+
ASSERT_EQUALS("[test.cpp:2] Unmatched ')'. Configuration: ''.", getSyntaxError(code));
1037+
}
1038+
1039+
{
1040+
const char code[] = "void f() {\n"
1041+
" int x = (3] + 0;\n" // <- error: unmatched ]
1042+
"}\n";
1043+
ASSERT_EQUALS("[test.cpp:2] Unmatched ']'. Configuration: ''.", getSyntaxError(code));
1044+
}
1045+
1046+
{
1047+
const char code[] = "void f() {\n" // <- error: unmatched {
1048+
" {\n"
1049+
"}\n";
1050+
ASSERT_EQUALS("[test.cpp:1] Unmatched '{'. Configuration: ''.", getSyntaxError(code));
10271051
}
10281052
}
10291053

0 commit comments

Comments
 (0)