Don't remove the volatile keyword so we can properly overload functions. (#1218)
* Don't remove the volatile keyword so we can properly overload functions. I fixed all the checks that had tests that use volatile. There will probably be more changes needed due to lack of test coverage for volatile in some checks. * Fix unused private function warning.
This commit is contained in:
parent
5452c4dc4a
commit
184537884f
|
@ -278,11 +278,11 @@ void CheckOther::warningOldStylePointerCast()
|
||||||
tok = scope->bodyStart;
|
tok = scope->bodyStart;
|
||||||
for (; tok && tok != scope->bodyEnd; tok = tok->next()) {
|
for (; tok && tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
// Old style pointer casting..
|
// Old style pointer casting..
|
||||||
if (!Token::Match(tok, "( const| %type% * const| ) (| %name%|%num%|%bool%|%char%|%str%"))
|
if (!Token::Match(tok, "( const|volatile| const|volatile| %type% * const| ) (| %name%|%num%|%bool%|%char%|%str%"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// skip first "const" in "const Type* const"
|
// skip first "const" in "const Type* const"
|
||||||
if (tok->strAt(1) == "const")
|
while (Token::Match(tok->next(), "const|volatile"))
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
const Token* typeTok = tok->next();
|
const Token* typeTok = tok->next();
|
||||||
// skip second "const" in "const Type* const"
|
// skip second "const" in "const Type* const"
|
||||||
|
@ -326,7 +326,7 @@ void CheckOther::invalidPointerCast()
|
||||||
const Token* toTok = nullptr;
|
const Token* toTok = nullptr;
|
||||||
const Token* fromTok = nullptr;
|
const Token* fromTok = nullptr;
|
||||||
// Find cast
|
// Find cast
|
||||||
if (Token::Match(tok, "( const| %type% %type%| const| * )")) {
|
if (Token::Match(tok, "( const|volatile| const|volatile| %type% %type%| const| * )")) {
|
||||||
toTok = tok;
|
toTok = tok;
|
||||||
fromTok = tok->astOperand1();
|
fromTok = tok->astOperand1();
|
||||||
} else if (Token::simpleMatch(tok, "reinterpret_cast <") && tok->linkAt(1)) {
|
} else if (Token::simpleMatch(tok, "reinterpret_cast <") && tok->linkAt(1)) {
|
||||||
|
|
|
@ -1406,8 +1406,8 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
|
||||||
tok1 = tok1->link()->tokAt(-2);
|
tok1 = tok1->link()->tokAt(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip over const, noexcept, throw and override specifiers
|
// skip over const, noexcept, throw, override, final and volatile specifiers
|
||||||
while (Token::Match(tok2, "const|noexcept|throw|override|final")) {
|
while (Token::Match(tok2, "const|noexcept|throw|override|final|volatile")) {
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
if (tok2 && tok2->str() == "(")
|
if (tok2 && tok2->str() == "(")
|
||||||
tok2 = tok2->link()->next();
|
tok2 = tok2->link()->next();
|
||||||
|
@ -1646,9 +1646,9 @@ void Variable::evaluate(const Library* lib)
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Token::Match(_start, "static|const %any%"))
|
while (Token::Match(_start, "static|const|volatile %any%"))
|
||||||
_start = _start->next();
|
_start = _start->next();
|
||||||
while (_end && _end->previous() && _end->str() == "const")
|
while (_end && _end->previous() && Token::Match(_end, "const|volatile"))
|
||||||
_end = _end->previous();
|
_end = _end->previous();
|
||||||
|
|
||||||
if (_start) {
|
if (_start) {
|
||||||
|
@ -1793,6 +1793,8 @@ Function::Function(const Tokenizer *_tokenizer, const Token *tok, const Scope *s
|
||||||
setFlag(fHasOverrideSpecifier, true);
|
setFlag(fHasOverrideSpecifier, true);
|
||||||
else if (tok->str() == "final")
|
else if (tok->str() == "final")
|
||||||
setFlag(fHasFinalSpecifier, true);
|
setFlag(fHasFinalSpecifier, true);
|
||||||
|
else if (tok->str() == "volatile")
|
||||||
|
isVolatile(true);
|
||||||
else if (tok->str() == "noexcept") {
|
else if (tok->str() == "noexcept") {
|
||||||
isNoExcept(!Token::simpleMatch(tok->next(), "( false )"));
|
isNoExcept(!Token::simpleMatch(tok->next(), "( false )"));
|
||||||
if (tok->next()->str() == "(")
|
if (tok->next()->str() == "(")
|
||||||
|
@ -2703,6 +2705,7 @@ void SymbolDatabase::printOut(const char *title) const
|
||||||
std::cout << " hasLvalRefQual: " << func->hasLvalRefQualifier() << std::endl;
|
std::cout << " hasLvalRefQual: " << func->hasLvalRefQualifier() << std::endl;
|
||||||
std::cout << " hasRvalRefQual: " << func->hasRvalRefQualifier() << std::endl;
|
std::cout << " hasRvalRefQual: " << func->hasRvalRefQualifier() << std::endl;
|
||||||
std::cout << " isVariadic: " << func->isVariadic() << std::endl;
|
std::cout << " isVariadic: " << func->isVariadic() << std::endl;
|
||||||
|
std::cout << " isVolatile: " << func->isVolatile() << std::endl;
|
||||||
std::cout << " attributes:";
|
std::cout << " attributes:";
|
||||||
if (func->isAttributeConst())
|
if (func->isAttributeConst())
|
||||||
std::cout << " const ";
|
std::cout << " const ";
|
||||||
|
@ -3057,7 +3060,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
||||||
|
|
||||||
const Token *typeTok = startTok;
|
const Token *typeTok = startTok;
|
||||||
// skip over stuff to get to type
|
// skip over stuff to get to type
|
||||||
while (Token::Match(typeTok, "const|enum|struct|::"))
|
while (Token::Match(typeTok, "const|volatile|enum|struct|::"))
|
||||||
typeTok = typeTok->next();
|
typeTok = typeTok->next();
|
||||||
if (Token::Match(typeTok, ",|)")) { // #8333
|
if (Token::Match(typeTok, ",|)")) { // #8333
|
||||||
symbolDatabase->_tokenizer->syntaxError(typeTok);
|
symbolDatabase->_tokenizer->syntaxError(typeTok);
|
||||||
|
@ -3069,7 +3072,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
||||||
|
|
||||||
// check for argument with no name or missing varid
|
// check for argument with no name or missing varid
|
||||||
if (!endTok) {
|
if (!endTok) {
|
||||||
if (tok->previous()->isName() && tok->strAt(-1) != "const") {
|
if (tok->previous()->isName() && !Token::Match(tok->tokAt(-1), "const|volatile")) {
|
||||||
if (tok->previous() != typeTok) {
|
if (tok->previous() != typeTok) {
|
||||||
nameTok = tok->previous();
|
nameTok = tok->previous();
|
||||||
endTok = nameTok->previous();
|
endTok = nameTok->previous();
|
||||||
|
@ -3100,7 +3103,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip over stuff before type
|
// skip over stuff before type
|
||||||
while (Token::Match(startTok, "enum|struct|const"))
|
while (Token::Match(startTok, "enum|struct|const|volatile"))
|
||||||
startTok = startTok->next();
|
startTok = startTok->next();
|
||||||
|
|
||||||
argumentList.emplace_back(nameTok, startTok, endTok, count++, Argument, argType, functionScope, &symbolDatabase->_settings->library);
|
argumentList.emplace_back(nameTok, startTok, endTok, count++, Argument, argType, functionScope, &symbolDatabase->_settings->library);
|
||||||
|
@ -3434,8 +3437,8 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess, con
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip const|static|mutable|extern
|
// skip const|volatile|static|mutable|extern
|
||||||
while (Token::Match(tok, "const|static|mutable|extern")) {
|
while (Token::Match(tok, "const|volatile|static|mutable|extern")) {
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -672,7 +672,8 @@ class CPPCHECKLIB Function {
|
||||||
fIsOperator = (1 << 16), ///< @brief is operator
|
fIsOperator = (1 << 16), ///< @brief is operator
|
||||||
fHasLvalRefQual = (1 << 17), ///< @brief has & lvalue ref-qualifier
|
fHasLvalRefQual = (1 << 17), ///< @brief has & lvalue ref-qualifier
|
||||||
fHasRvalRefQual = (1 << 18), ///< @brief has && rvalue ref-qualifier
|
fHasRvalRefQual = (1 << 18), ///< @brief has && rvalue ref-qualifier
|
||||||
fIsVariadic = (1 << 19) ///< @brief is variadic
|
fIsVariadic = (1 << 19), ///< @brief is variadic
|
||||||
|
fIsVolatile = (1 << 20) ///< @brief is volatile
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -808,6 +809,9 @@ public:
|
||||||
bool isVariadic() const {
|
bool isVariadic() const {
|
||||||
return getFlag(fIsVariadic);
|
return getFlag(fIsVariadic);
|
||||||
}
|
}
|
||||||
|
bool isVolatile() const {
|
||||||
|
return getFlag(fIsVolatile);
|
||||||
|
}
|
||||||
|
|
||||||
void hasBody(bool state) {
|
void hasBody(bool state) {
|
||||||
setFlag(fHasBody, state);
|
setFlag(fHasBody, state);
|
||||||
|
@ -893,6 +897,9 @@ private:
|
||||||
void isVariadic(bool state) {
|
void isVariadic(bool state) {
|
||||||
setFlag(fIsVariadic, state);
|
setFlag(fIsVariadic, state);
|
||||||
}
|
}
|
||||||
|
void isVolatile(bool state) {
|
||||||
|
setFlag(fIsVolatile, state);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CPPCHECKLIB Scope {
|
class CPPCHECKLIB Scope {
|
||||||
|
|
|
@ -3635,7 +3635,7 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
||||||
if (_settings->terminated())
|
if (_settings->terminated())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Remove "volatile", "inline", "register", and "restrict"
|
// Remove "inline", "register", and "restrict"
|
||||||
simplifyKeyword();
|
simplifyKeyword();
|
||||||
|
|
||||||
// simplify simple calculations inside <..>
|
// simplify simple calculations inside <..>
|
||||||
|
@ -4169,7 +4169,7 @@ void Tokenizer::removeMacrosInGlobalScope()
|
||||||
if (tok->str() == "(") {
|
if (tok->str() == "(") {
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
if (Token::Match(tok, ") %type% {") &&
|
if (Token::Match(tok, ") %type% {") &&
|
||||||
!Token::Match(tok->next(), "const|namespace|class|struct|union|noexcept|override|final"))
|
!Token::Match(tok->next(), "const|namespace|class|struct|union|noexcept|override|final|volatile"))
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5521,10 +5521,10 @@ void Tokenizer::simplifyFunctionPointers()
|
||||||
Token *endTok = tok->link()->next()->link();
|
Token *endTok = tok->link()->next()->link();
|
||||||
if (Token::simpleMatch(endTok, ") throw ("))
|
if (Token::simpleMatch(endTok, ") throw ("))
|
||||||
endTok = endTok->linkAt(2);
|
endTok = endTok->linkAt(2);
|
||||||
if (!Token::Match(endTok, ") const| ;|,|)|=|[|{"))
|
if (!Token::Match(endTok, ") const|volatile| const|volatile| ;|,|)|=|[|{"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (endTok->strAt(1) == "const")
|
while (Token::Match(endTok->next(), "const|volatile"))
|
||||||
endTok->deleteNext();
|
endTok->deleteNext();
|
||||||
|
|
||||||
// ok simplify this function pointer to an ordinary pointer
|
// ok simplify this function pointer to an ordinary pointer
|
||||||
|
@ -8960,8 +8960,7 @@ void Tokenizer::simplifyCPPAttribute()
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::set<std::string> keywords = {
|
static const std::set<std::string> keywords = {
|
||||||
"volatile"
|
"inline"
|
||||||
, "inline"
|
|
||||||
, "_inline"
|
, "_inline"
|
||||||
, "__inline"
|
, "__inline"
|
||||||
, "__forceinline"
|
, "__forceinline"
|
||||||
|
@ -8969,7 +8968,7 @@ static const std::set<std::string> keywords = {
|
||||||
, "__restrict"
|
, "__restrict"
|
||||||
, "__restrict__"
|
, "__restrict__"
|
||||||
};
|
};
|
||||||
// Remove "volatile", "inline", "register", "restrict", "override", "final", "static" and "constexpr"
|
// Remove "inline", "register", "restrict", "override", "final", "static" and "constexpr"
|
||||||
// "restrict" keyword
|
// "restrict" keyword
|
||||||
// - New to 1999 ANSI/ISO C standard
|
// - New to 1999 ANSI/ISO C standard
|
||||||
// - Not in C++ standard yet
|
// - Not in C++ standard yet
|
||||||
|
|
|
@ -238,8 +238,7 @@ private:
|
||||||
" std::cout << k << std::endl;\n"
|
" std::cout << k << std::endl;\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}");
|
"}");
|
||||||
TODO_ASSERT_EQUALS("",
|
ASSERT_EQUALS("[test.cpp:6]: (performance) Prefer prefix ++/-- operators for non-primitive types.\n", errout.str());
|
||||||
"[test.cpp:6]: (performance) Prefer prefix ++/-- operators for non-primitive types.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void testiterator() {
|
void testiterator() {
|
||||||
|
|
|
@ -1187,7 +1187,7 @@ private:
|
||||||
void simplifyTypedef39() {
|
void simplifyTypedef39() {
|
||||||
const char code[] = "typedef int A;\n"
|
const char code[] = "typedef int A;\n"
|
||||||
"template <const A, volatile A> struct S{};";
|
"template <const A, volatile A> struct S{};";
|
||||||
const char expected[] = "template < const int , int > struct S { } ;";
|
const char expected[] = "template < const int , volatile int > struct S { } ;";
|
||||||
ASSERT_EQUALS(expected, tok(code, false));
|
ASSERT_EQUALS(expected, tok(code, false));
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
@ -1478,7 +1478,7 @@ private:
|
||||||
"_Iterator v3;";
|
"_Iterator v3;";
|
||||||
|
|
||||||
// The expected result..
|
// The expected result..
|
||||||
const char expected[] = "long * const v1 ; "
|
const char expected[] = "volatile long * const v1 ; "
|
||||||
"void * const v2 [ 2 ] ; "
|
"void * const v2 [ 2 ] ; "
|
||||||
"int * const * v3 ;";
|
"int * const * v3 ;";
|
||||||
ASSERT_EQUALS(expected, tok(code));
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
|
@ -2931,16 +2931,16 @@ private:
|
||||||
// The expected result..
|
// The expected result..
|
||||||
const char expected[] = "int * t1 ; " // simplified to regular pointer
|
const char expected[] = "int * t1 ; " // simplified to regular pointer
|
||||||
"int * const t2 ; "
|
"int * const t2 ; "
|
||||||
"int * t3 ; " // volatile removed, gets simplified to regular pointer
|
"int * volatile t3 ; "
|
||||||
"int * const t4 ; " // volatile removed
|
"int * const volatile t4 ; "
|
||||||
"int * t5 ; "
|
"int * t5 ; "
|
||||||
"int * const t6 ; "
|
"int * const t6 ; "
|
||||||
"int * t7 ; " // volatile removed
|
"int * volatile t7 ; "
|
||||||
"int * const t8 ; " // volatile removed
|
"int * const volatile t8 ; "
|
||||||
"int ( :: C :: * t9 ) ( float ) ; "
|
"int ( :: C :: * t9 ) ( float ) ; "
|
||||||
"int ( :: C :: * const t10 ) ( float ) ; "
|
"int ( :: C :: * const t10 ) ( float ) ; "
|
||||||
"int ( :: C :: * t11 ) ( float ) ; " // volatile removed
|
"int ( :: C :: * volatile t11 ) ( float ) ; "
|
||||||
"int ( :: C :: * const t12 ) ( float ) ;"; // volatile removed
|
"int ( :: C :: * const volatile t12 ) ( float ) ;";
|
||||||
ASSERT_EQUALS(expected, tok(code, false));
|
ASSERT_EQUALS(expected, tok(code, false));
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
@ -3005,8 +3005,8 @@ private:
|
||||||
// The expected result..
|
// The expected result..
|
||||||
const char expected[] = ":: C ( :: C :: * f1 ) ( ) ; "
|
const char expected[] = ":: C ( :: C :: * f1 ) ( ) ; "
|
||||||
":: C ( :: C :: * f2 ) ( ) const ; "
|
":: C ( :: C :: * f2 ) ( ) const ; "
|
||||||
":: C ( :: C :: * f3 ) ( ) ; "
|
":: C ( :: C :: * f3 ) ( ) volatile ; "
|
||||||
":: C ( :: C :: * f4 ) ( ) const ;";
|
":: C ( :: C :: * f4 ) ( ) const volatile ;";
|
||||||
ASSERT_EQUALS(expected, tok(code));
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
@ -3043,8 +3043,8 @@ private:
|
||||||
// The expected result..
|
// The expected result..
|
||||||
const char expected[] = ":: B :: C ( :: B :: C :: * f1 ) ( ) ; "
|
const char expected[] = ":: B :: C ( :: B :: C :: * f1 ) ( ) ; "
|
||||||
":: B :: C ( :: B :: C :: * f2 ) ( ) const ; "
|
":: B :: C ( :: B :: C :: * f2 ) ( ) const ; "
|
||||||
":: B :: C ( :: B :: C :: * f3 ) ( ) ; "
|
":: B :: C ( :: B :: C :: * f3 ) ( ) volatile ; "
|
||||||
":: B :: C ( :: B :: C :: * f4 ) ( ) const ;";
|
":: B :: C ( :: B :: C :: * f4 ) ( ) const volatile ;";
|
||||||
ASSERT_EQUALS(expected, tok(code));
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,6 +286,7 @@ private:
|
||||||
TEST_CASE(symboldatabase66); // #8540
|
TEST_CASE(symboldatabase66); // #8540
|
||||||
TEST_CASE(symboldatabase67); // #8538
|
TEST_CASE(symboldatabase67); // #8538
|
||||||
TEST_CASE(symboldatabase68); // #8560
|
TEST_CASE(symboldatabase68); // #8560
|
||||||
|
TEST_CASE(symboldatabase69);
|
||||||
|
|
||||||
TEST_CASE(enum1);
|
TEST_CASE(enum1);
|
||||||
TEST_CASE(enum2);
|
TEST_CASE(enum2);
|
||||||
|
@ -3864,6 +3865,28 @@ private:
|
||||||
ASSERT(f && f->function() && f->function()->isNoExcept());
|
ASSERT(f && f->function() && f->function()->isNoExcept());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void symboldatabase69() {
|
||||||
|
GET_SYMBOL_DB("struct Fred {\n"
|
||||||
|
" int x, y;\n"
|
||||||
|
" void foo() volatile { }\n"
|
||||||
|
" void foo() const { }\n"
|
||||||
|
" void foo() { }\n"
|
||||||
|
"};");
|
||||||
|
const Token *f = db ? Token::findsimplematch(tokenizer.tokens(), "foo ( ) volatile {") : nullptr;
|
||||||
|
ASSERT(f != nullptr);
|
||||||
|
ASSERT(f && f->function() && f->function()->token->linenr() == 3);
|
||||||
|
ASSERT(f && f->function() && f->function()->isVolatile());
|
||||||
|
f = db ? Token::findsimplematch(tokenizer.tokens(), "foo ( ) const {") : nullptr;
|
||||||
|
ASSERT(f != nullptr);
|
||||||
|
ASSERT(f && f->function() && f->function()->token->linenr() == 4);
|
||||||
|
ASSERT(f && f->function() && f->function()->isConst());
|
||||||
|
f = db ? Token::findsimplematch(tokenizer.tokens(), "foo ( ) {") : nullptr;
|
||||||
|
ASSERT(f != nullptr);
|
||||||
|
ASSERT(f && f->function() && f->function()->token->linenr() == 5);
|
||||||
|
ASSERT(f && f->function() && !f->function()->isVolatile());
|
||||||
|
ASSERT(f && f->function() && !f->function()->isConst());
|
||||||
|
}
|
||||||
|
|
||||||
void enum1() {
|
void enum1() {
|
||||||
GET_SYMBOL_DB("enum BOOL { FALSE, TRUE }; enum BOOL b;");
|
GET_SYMBOL_DB("enum BOOL { FALSE, TRUE }; enum BOOL b;");
|
||||||
|
|
||||||
|
|
|
@ -4033,7 +4033,7 @@ private:
|
||||||
|
|
||||||
const std::string actual(tokenizeAndStringify(code));
|
const std::string actual(tokenizeAndStringify(code));
|
||||||
|
|
||||||
ASSERT_EQUALS("int a ; a = 0 ;\nint b ; b = 0 ;\nint c ; c = 0 ;", actual);
|
ASSERT_EQUALS("volatile int a ; a = 0 ;\nvolatile int b ; b = 0 ;\nvolatile int c ; c = 0 ;", actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue