Ticket #6620, #6685: Reserved keywords cannot be function names.

This commit is contained in:
Simon Martin 2015-05-22 22:18:42 +02:00
parent f0bc300198
commit 67eab0cd7c
6 changed files with 49 additions and 5 deletions

View File

@ -745,6 +745,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
// save function prototype in database
if (newFunc) {
Function* func = addGlobalFunctionDecl(scope, tok, argStart, funcStart);
if (!func)
break;
if (Token::Match(argStart->link(), ") const| noexcept")) {
int arg = 2;
@ -1658,6 +1660,9 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co
if (!function)
function = addGlobalFunctionDecl(scope, tok, argStart, funcStart);
if (!function)
return 0;
function->arg = argStart;
function->token = funcStart;
function->hasBody(true);
@ -1683,6 +1688,8 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok,
function.access = Public;
// save the function name location
if (funcStart && isReservedName(funcStart->str()))
return 0;
function.tokenDef = funcStart;
function.isInline(false);
@ -3588,3 +3595,28 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n
return const_cast<Function *>(function);
}
//---------------------------------------------------------------------------
bool SymbolDatabase::isReservedName(const std::string& iName) const
{
static const std::set<std::string> c_keywords = make_container<std::set<std::string>>() <<
"auto" << "break" << "case" << "char" << "const" << "continue" << "default" << "do" <<
"double" << "else" << "enum" << "extern" << "float" << "for" << "goto" << "if" << "inline" <<
"int" << "long" << "register" << "restrict" << "return" << "short" << "signed" << "sizeof" <<
"static" << "struct" << "switch" << "typedef" << "union" << "unsigned" << "void" << "volatile" <<
"while";
static const std::set<std::string> cpp_keywords = make_container<std::set<std::string>>() <<
"alignas" << "alignof" << "and" << "and_eq" << "asm" << "auto" << "bitand" << "bitor" << "bool" <<
"break" << "case" << "catch" << "char" << "char16_t" << "char32_t" << "class" << "compl" <<
"concept" << "const" << "constexpr" << "const_cast" << "continue" << "decltype" << "default" <<
"delete" << "do" << "double" << "dynamic_cast" << "else" << "enum" << "explicit" << "export" <<
"extern" << "false" << "float" << "for" << "friend" << "goto" << "if" << "inline" << "int" << "long" <<
"mutable" << "namespace" << "new" << "noexcept" << "not" << "not_eq" << "nullptr" << "operator" <<
"or" << "or_eq" << "private" << "protected" << "public" << "register" << "reinterpret_cast" <<
"requires" << "return" << "short" << "signed" << "sizeof" << "static" << "static_assert" <<
"static_cast" << "struct" << "switch" << "template" << "this" << "thread_local" << "throw" <<
"true" << "try" << "typedef" << "typeid" << "typename" << "union" << "unsigned" << "using" <<
"virtual" << "void" << "volatile" << "wchar_t" << "while" << "xor" << "xor_eq";
return (c_keywords.find(iName) != c_keywords.cend()) || (isCPP() && (cpp_keywords.find(iName) != cpp_keywords.cend()));
}

View File

@ -1005,6 +1005,9 @@ private:
const Scope *findNamespace(const Token * tok, const Scope * scope) const;
Function *findFunctionInScope(const Token *func, const Scope *ns);
/** Whether iName is a keyword as defined in http://en.cppreference.com/w/c/keyword and http://en.cppreference.com/w/cpp/keyword*/
bool isReservedName(const std::string& iName) const;
const Tokenizer *_tokenizer;
const Settings *_settings;

View File

@ -78,6 +78,8 @@ private:
TEST_CASE(garbageCode37); // #5166
TEST_CASE(garbageCode38); // #6666
TEST_CASE(garbageCode39); // #6686
TEST_CASE(garbageCode40); // #6620
TEST_CASE(garbageCode41); // #6685
TEST_CASE(garbageValueFlow);
TEST_CASE(garbageSymbolDatabase);
@ -455,6 +457,14 @@ private:
checkCode("({ (); strcat(strcat(() ()) ()) })");
}
void garbageCode40() { // #6620
ASSERT_THROW(checkCode("{ ( ) () { virtual } ; { } E } A { : { } ( ) } * const ( ) const { }"), InternalError);
}
void garbageCode41() { // #6685
ASSERT_THROW(checkCode(" { } { return } *malloc(__SIZE_TYPE__ size); *memcpy(void n); static * const () { memcpy (*slot, 3); } { (); } { }"), InternalError);
}
void garbageValueFlow() {
// #6089
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"

View File

@ -805,7 +805,7 @@ private:
ASSERT_EQUALS("\n\n##file 0\n1: else { if ( ab ) { cd } else { ef } } gh\n", elseif(code));
// syntax error: assert there is no segmentation fault
ASSERT_EQUALS("\n\n##file 0\n1: else if ( x ) { }\n", elseif("else if (x) { }"));
ASSERT_THROW(elseif("else if (x) { }"), InternalError);
{
const char src[] = "void f(int g,int f) {\n"

View File

@ -1919,8 +1919,7 @@ private:
}
void symboldatabase36() { // ticket #4892
check("void struct ( ) { if ( 1 ) } int main ( ) { }");
ASSERT_EQUALS("", errout.str());
ASSERT_THROW(check("void struct ( ) { if ( 1 ) } int main ( ) { }"), InternalError);
}
void symboldatabase37() {

View File

@ -1270,7 +1270,7 @@ private:
void ifAddBraces15() {
// ticket #2616 - unknown macro before if
ASSERT_EQUALS("{ A if ( x ) { y ( ) ; } }", tokenizeAndStringify("{A if(x)y();}", false));
ASSERT_THROW(tokenizeAndStringify("{A if(x)y();}", false), InternalError);
}
void ifAddBraces16() { // ticket # 2739 (segmentation fault)
@ -6145,7 +6145,7 @@ private:
"operator ( ) ; "
"}";
ASSERT_EQUALS(result, tokenizeAndStringify(code,false));
ASSERT_EQUALS(result, tokenizeAndStringify(code, /*simplify=*/false, /*expand=*/true, /*platform=*/Settings::Unspecified, "test.c"));
}
void simplifyOperatorName2() {