Tokenizer: Write syntax error if there is C++ code in C file.
This commit is contained in:
parent
fd2651909c
commit
50da7d4919
|
@ -3318,6 +3318,9 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
|||
}
|
||||
}
|
||||
|
||||
// Is there C++ code in C file?
|
||||
validateC();
|
||||
|
||||
// remove MACRO in variable declaration: MACRO int x;
|
||||
removeMacroInVarDecl();
|
||||
|
||||
|
@ -7617,6 +7620,12 @@ void Tokenizer::syntaxError(const Token *tok, char c) const
|
|||
InternalError::SYNTAX);
|
||||
}
|
||||
|
||||
void Tokenizer::syntaxErrorC(const Token *tok, const std::string &what) const
|
||||
{
|
||||
printDebugOutput(0);
|
||||
throw InternalError(tok, "Code '"+what+"' is invalid C code. Use --std or --language to configure the language.", InternalError::SYNTAX);
|
||||
}
|
||||
|
||||
void Tokenizer::unhandled_macro_class_x_y(const Token *tok) const
|
||||
{
|
||||
reportError(tok,
|
||||
|
@ -7996,6 +8005,24 @@ void Tokenizer::simplifyComma()
|
|||
}
|
||||
|
||||
|
||||
void Tokenizer::validateC() const
|
||||
{
|
||||
if (!isC())
|
||||
return;
|
||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
||||
if (tok->previous() && !Token::Match(tok->previous(), "[;{}]"))
|
||||
continue;
|
||||
if (Token::simpleMatch(tok, "using namespace std ;"))
|
||||
syntaxErrorC(tok, "using namespace std");
|
||||
if (Token::Match(tok, "template < class %name% [,>]"))
|
||||
syntaxErrorC(tok, "template<...");
|
||||
if (Token::Match(tok, "%name% :: %name%"))
|
||||
syntaxErrorC(tok, tok->str() + tok->strAt(1) + tok->strAt(2));
|
||||
if (Token::Match(tok, "class|namespace %name% [:{]"))
|
||||
syntaxErrorC(tok, tok->str() + tok->strAt(1) + tok->strAt(2));
|
||||
}
|
||||
}
|
||||
|
||||
void Tokenizer::validate() const
|
||||
{
|
||||
std::stack<const Token *> linkTokens;
|
||||
|
|
|
@ -568,11 +568,19 @@ public:
|
|||
/** Syntax error. Example: invalid number of ')' */
|
||||
void syntaxError(const Token *tok, char c) const;
|
||||
|
||||
/** Syntax error. C++ code in C file. */
|
||||
void syntaxErrorC(const Token *tok, const std::string &what) const;
|
||||
|
||||
private:
|
||||
|
||||
/** Report that there is an unhandled "class x y {" code */
|
||||
void unhandled_macro_class_x_y(const Token *tok) const;
|
||||
|
||||
/**
|
||||
* Is there C++ code in C file?
|
||||
*/
|
||||
void validateC() const;
|
||||
|
||||
/**
|
||||
* assert that tokens are ok - used during debugging for example
|
||||
* to catch problems in simplifyTokenList1/2.
|
||||
|
|
|
@ -130,7 +130,6 @@ private:
|
|||
TEST_CASE(garbageCode90);
|
||||
TEST_CASE(garbageCode91);
|
||||
TEST_CASE(garbageCode92);
|
||||
TEST_CASE(garbageCode93);
|
||||
TEST_CASE(garbageCode94);
|
||||
TEST_CASE(garbageCode95);
|
||||
TEST_CASE(garbageCode96);
|
||||
|
@ -763,10 +762,6 @@ private:
|
|||
ASSERT_THROW(checkCode("template < typename _Tp ( ( ) ; _Tp ) , decltype > { } { ( ) ( ) }"), InternalError); // do not crash
|
||||
}
|
||||
|
||||
void garbageCode93() { // #6800
|
||||
checkCode(" namespace A { } class A{ { }} class A : T ;", false); // do not crash
|
||||
}
|
||||
|
||||
void garbageCode94() { // #6803
|
||||
//checkCode("typedef long __m256i __attribute__ ( ( ( ) ) )[ ; ( ) { } typedef __m256i __attribute__ ( ( ( ) ) ) < ] ( ) { ; }");
|
||||
ASSERT_THROW(checkCode("typedef long __m256i __attribute__ ( ( ( ) ) )[ ; ( ) { } typedef __m256i __attribute__ ( ( ( ) ) ) < ] ( ) { ; }"), InternalError);
|
||||
|
@ -1326,7 +1321,7 @@ private:
|
|||
|
||||
void garbageCode164() {
|
||||
//7234
|
||||
checkCode("class d{k p;}(){d::d():B<()}", false);
|
||||
checkCode("class d{k p;}(){d::d():B<()}");
|
||||
}
|
||||
|
||||
void garbageCode165() {
|
||||
|
@ -1336,7 +1331,7 @@ private:
|
|||
|
||||
void garbageCode167() {
|
||||
//7237
|
||||
checkCode("class D00i000{:D00i000::}i", false);
|
||||
ASSERT_THROW(checkCode("class D00i000{:D00i000::}i"),InternalError);
|
||||
}
|
||||
|
||||
void garbageCode168() {
|
||||
|
|
|
@ -864,7 +864,7 @@ private:
|
|||
" ::exit(0);\n"
|
||||
" }"
|
||||
" free(p);\n"
|
||||
"}");
|
||||
"}", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
|
@ -874,7 +874,7 @@ private:
|
|||
" std::exit(0);\n"
|
||||
" }"
|
||||
" free(p);\n"
|
||||
"}");
|
||||
"}", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
|
|
@ -1104,15 +1104,8 @@ private:
|
|||
std::istringstream istr(code);
|
||||
tokenizerCpp.tokenize(istr, "test.cpp");
|
||||
|
||||
Tokenizer tokenizerC(&settings, this);
|
||||
std::istringstream istr2(code);
|
||||
tokenizerC.tokenize(istr2, "test.c");
|
||||
|
||||
CheckOther checkOtherCpp(&tokenizerCpp, &settings, this);
|
||||
checkOtherCpp.warningOldStylePointerCast();
|
||||
|
||||
CheckOther checkOtherC(&tokenizerC, &settings, this);
|
||||
checkOtherC.warningOldStylePointerCast();
|
||||
}
|
||||
|
||||
void oldStylePointerCast() {
|
||||
|
|
|
@ -64,6 +64,8 @@ private:
|
|||
TEST_CASE(tokenize32); // #5884 (fsanitize=undefined: left shift of negative value -10000 in lib/templatesimplifier.cpp:852:46)
|
||||
TEST_CASE(tokenize33); // #5780 Various crashes on valid template code
|
||||
|
||||
TEST_CASE(validate);
|
||||
|
||||
TEST_CASE(syntax_case_default);
|
||||
|
||||
TEST_CASE(foreach); // #3690
|
||||
|
@ -780,6 +782,13 @@ private:
|
|||
tokenizeAndStringify(code, true);
|
||||
}
|
||||
|
||||
void validate() {
|
||||
// C++ code in C file
|
||||
ASSERT_THROW(tokenizeAndStringify(";using namespace std;",false,false,Settings::Native,"test.c"), InternalError);
|
||||
ASSERT_THROW(tokenizeAndStringify(";std::map<int,int> m;",false,false,Settings::Native,"test.c"), InternalError);
|
||||
ASSERT_THROW(tokenizeAndStringify(";template<class T> class X { };",false,false,Settings::Native,"test.c"), InternalError);
|
||||
}
|
||||
|
||||
void syntax_case_default() { // correct syntax
|
||||
tokenizeAndStringify("void f() {switch (n) { case 0: z(); break;}}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
|
Loading…
Reference in New Issue