Skip to content

Commit 3db72cf

Browse files
authored
fix #13629: AST: syntax error reported for code 'virtual ~Foo() throw() = delete;' & #13626: AST: skip rvalue ref-specifier for method (#7297)
1 parent f447521 commit 3db72cf

File tree

9 files changed

+137
-109
lines changed

9 files changed

+137
-109
lines changed

lib/checkclass.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3340,11 +3340,10 @@ void CheckClass::checkUselessOverride()
33403340
continue;
33413341
if (Token::simpleMatch(call->astParent(), "."))
33423342
continue;
3343-
std::vector<const Token*> funcArgs = getArguments(func.tokenDef);
33443343
std::vector<const Token*> callArgs = getArguments(call);
3345-
if (funcArgs.size() != callArgs.size() ||
3346-
!std::equal(funcArgs.begin(), funcArgs.end(), callArgs.begin(), [](const Token* t1, const Token* t2) {
3347-
return t1->str() == t2->str();
3344+
if (func.argumentList.size() != callArgs.size() ||
3345+
!std::equal(func.argumentList.begin(), func.argumentList.end(), callArgs.begin(), [](const Variable& v, const Token* t) {
3346+
return v.nameToken() && v.nameToken()->str() == t->str();
33483347
}))
33493348
continue;
33503349
uselessOverrideError(baseFunc, &func);

lib/symboldatabase.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
218218
// skip variable declaration
219219
else if (Token::Match(tok2, "*|&|>"))
220220
continue;
221-
else if (Token::Match(tok2, "%name% (") && Tokenizer::isFunctionHead(tok2->next(), "{;"))
221+
else if (Token::Match(tok2, "%name% (") && TokenList::isFunctionHead(tok2->next(), "{;"))
222222
continue;
223223
else if (Token::Match(tok2, "%name% [|="))
224224
continue;
@@ -562,7 +562,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
562562
function.arg = function.argDef;
563563

564564
// out of line function
565-
if (const Token *endTok = Tokenizer::isFunctionHead(end, ";")) {
565+
if (const Token *endTok = TokenList::isFunctionHead(end, ";")) {
566566
tok = endTok;
567567
scope->addFunction(std::move(function));
568568
}
@@ -1942,7 +1942,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
19421942
const Token* tok1 = tok->previous();
19431943
const Token* tok2 = tok->linkAt(1)->next();
19441944

1945-
if (!Tokenizer::isFunctionHead(tok->next(), ";:{"))
1945+
if (!TokenList::isFunctionHead(tok->next(), ";:{"))
19461946
return false;
19471947

19481948
// skip over destructor "~"
@@ -2607,7 +2607,7 @@ Function::Function(const Token *tok,
26072607
tok = tok->next();
26082608
}
26092609

2610-
if (Tokenizer::isFunctionHead(end, ":{")) {
2610+
if (TokenList::isFunctionHead(end, ":{")) {
26112611
// assume implementation is inline (definition and implementation same)
26122612
token = tokenDef;
26132613
arg = argDef;
@@ -3320,7 +3320,7 @@ void SymbolDatabase::addClassFunction(Scope *&scope, const Token *&tok, const To
33203320
if (!func->hasBody()) {
33213321
const Token *closeParen = tok->linkAt(1);
33223322
if (closeParen) {
3323-
const Token *eq = Tokenizer::isFunctionHead(closeParen, ";");
3323+
const Token *eq = TokenList::isFunctionHead(closeParen, ";");
33243324
if (eq && Token::simpleMatch(eq->tokAt(-2), "= default ;")) {
33253325
func->isDefault(true);
33263326
return;
@@ -3395,7 +3395,7 @@ void SymbolDatabase::addClassFunction(Scope *&scope, const Token *&tok, const To
33953395
if (func->argsMatch(scope1, func->argDef, tok->next(), path, path_length)) {
33963396
const Token *closeParen = tok->linkAt(1);
33973397
if (closeParen) {
3398-
const Token *eq = Tokenizer::isFunctionHead(closeParen, ";");
3398+
const Token *eq = TokenList::isFunctionHead(closeParen, ";");
33993399
if (eq && Token::simpleMatch(eq->tokAt(-2), "= default ;")) {
34003400
func->isDefault(true);
34013401
return;

lib/templatesimplifier.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,14 +1442,14 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *to
14421442
} else if (Token::Match(tok->next(), "%type% <")) {
14431443
const Token *closing = tok->tokAt(2)->findClosingBracket();
14441444
if (closing) {
1445-
if (closing->strAt(1) == "(" && Tokenizer::isFunctionHead(closing->next(), ";|{|:"))
1445+
if (closing->strAt(1) == "(" && TokenList::isFunctionHead(closing->next(), ";|{|:"))
14461446
return true;
14471447
while (tok->next() && tok->next() != closing) {
14481448
tok = tok->next();
14491449
namepos++;
14501450
}
14511451
}
1452-
} else if (Token::Match(tok->next(), "%type% (") && Tokenizer::isFunctionHead(tok->tokAt(2), ";|{|:")) {
1452+
} else if (Token::Match(tok->next(), "%type% (") && TokenList::isFunctionHead(tok->tokAt(2), ";|{|:")) {
14531453
return true;
14541454
}
14551455
tok = tok->next();
@@ -1955,7 +1955,7 @@ void TemplateSimplifier::expandTemplate(
19551955
const Token *tok4 = tok3->next()->findClosingBracket();
19561956
while (tok4 && tok4->str() != "(")
19571957
tok4 = tok4->next();
1958-
if (!Tokenizer::isFunctionHead(tok4, ":{"))
1958+
if (!TokenList::isFunctionHead(tok4, ":{"))
19591959
continue;
19601960
// find function return type start
19611961
tok5 = tok5->next()->findClosingBracket();

lib/tokenize.cpp

Lines changed: 22 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -99,63 +99,6 @@ static void skipEnumBody(T *&tok)
9999
tok = defStart->link()->next();
100100
}
101101

102-
const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &endsWith)
103-
{
104-
if (!tok)
105-
return nullptr;
106-
if (tok->str() == "(")
107-
tok = tok->link();
108-
if (tok->str() != ")")
109-
return nullptr;
110-
if (!tok->isCpp() && !Token::Match(tok->link()->previous(), "%name%|(|)"))
111-
return nullptr;
112-
if (Token::Match(tok, ") ;|{|[")) {
113-
tok = tok->next();
114-
while (tok && tok->str() == "[" && tok->link()) {
115-
if (endsWith.find(tok->str()) != std::string::npos)
116-
return tok;
117-
tok = tok->link()->next();
118-
}
119-
return (tok && endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr;
120-
}
121-
if (tok->isCpp() && tok->str() == ")") {
122-
tok = tok->next();
123-
while (Token::Match(tok, "const|noexcept|override|final|volatile|mutable|&|&& !!(") ||
124-
(Token::Match(tok, "%name% !!(") && tok->isUpperCaseName()))
125-
tok = tok->next();
126-
if (tok && tok->str() == ")")
127-
tok = tok->next();
128-
while (tok && tok->str() == "[")
129-
tok = tok->link()->next();
130-
if (Token::Match(tok, "throw|noexcept ("))
131-
tok = tok->linkAt(1)->next();
132-
if (Token::Match(tok, "%name% (") && tok->isUpperCaseName())
133-
tok = tok->linkAt(1)->next();
134-
if (tok && tok->originalName() == "->") { // trailing return type
135-
for (tok = tok->next(); tok && !Token::Match(tok, ";|{|override|final|}|)|]"); tok = tok->next())
136-
if (tok->link() && Token::Match(tok, "<|[|("))
137-
tok = tok->link();
138-
}
139-
while (Token::Match(tok, "override|final !!(") ||
140-
(Token::Match(tok, "%name% !!(") && tok->isUpperCaseName()))
141-
tok = tok->next();
142-
if (Token::Match(tok, "= 0|default|delete ;"))
143-
tok = tok->tokAt(2);
144-
if (Token::simpleMatch(tok, "requires")) {
145-
for (tok = tok->next(); tok && !Token::Match(tok, ";|{|}|)|]"); tok = tok->next()) {
146-
if (tok->link() && Token::Match(tok, "<|[|("))
147-
tok = tok->link();
148-
if (Token::simpleMatch(tok, "bool {"))
149-
tok = tok->linkAt(1);
150-
}
151-
}
152-
if (tok && tok->str() == ":" && !Token::Match(tok->next(), "%name%|::"))
153-
return nullptr;
154-
return (tok && endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr;
155-
}
156-
return nullptr;
157-
}
158-
159102
/**
160103
* is tok the start brace { of a class, struct, union, or enum
161104
*/
@@ -1476,7 +1419,7 @@ void Tokenizer::simplifyTypedefCpp()
14761419
}
14771420

14781421
// function
1479-
else if (isFunctionHead(tokOffset->link(), ";,")) {
1422+
else if (TokenList::isFunctionHead(tokOffset->link(), ";,")) {
14801423
function = true;
14811424
if (tokOffset->link()->strAt(1) == "const") {
14821425
specStart = tokOffset->link()->next();
@@ -1774,7 +1717,7 @@ void Tokenizer::simplifyTypedefCpp()
17741717
}
17751718

17761719
// check for member functions
1777-
else if (cpp && tok2->str() == "(" && isFunctionHead(tok2, "{:")) {
1720+
else if (cpp && tok2->str() == "(" && TokenList::isFunctionHead(tok2, "{:")) {
17781721
const Token *func = tok2->previous();
17791722

17801723
/** @todo add support for multi-token operators */
@@ -2842,7 +2785,7 @@ bool Tokenizer::isMemberFunction(const Token *openParen)
28422785
{
28432786
return (Token::Match(openParen->tokAt(-2), ":: %name% (") ||
28442787
Token::Match(openParen->tokAt(-3), ":: ~ %name% (")) &&
2845-
isFunctionHead(openParen, "{|:");
2788+
TokenList::isFunctionHead(openParen, "{|:");
28462789
}
28472790

28482791
static bool scopesMatch(const std::string &scope1, const std::string &scope2, const ScopeInfo3 *globalScope)
@@ -3976,7 +3919,7 @@ const Token * Tokenizer::startOfExecutableScope(const Token * tok)
39763919
if (tok->str() != ")")
39773920
return nullptr;
39783921

3979-
tok = Tokenizer::isFunctionHead(tok, ":{");
3922+
tok = TokenList::isFunctionHead(tok, ":{");
39803923

39813924
if (Token::Match(tok, ": %name% [({]")) {
39823925
while (Token::Match(tok, "[:,] %name% [({]"))
@@ -4408,7 +4351,7 @@ static void setVarIdStructMembers(Token *&tok1,
44084351
while (Token::Match(tok->next(), ")| . %name% !!(")) {
44094352
// Don't set varid for trailing return type
44104353
if (tok->strAt(1) == ")" && Token::Match(tok->linkAt(1)->tokAt(-1), "%name%|]") &&
4411-
Tokenizer::isFunctionHead(tok->linkAt(1), "{|;")) {
4354+
TokenList::isFunctionHead(tok->linkAt(1), "{|;")) {
44124355
tok = tok->tokAt(3);
44134356
continue;
44144357
}
@@ -4623,7 +4566,7 @@ void Tokenizer::setVarIdPass1()
46234566
} else if (!initlist && tok->str()=="(") {
46244567
const Token * newFunctionDeclEnd = nullptr;
46254568
if (!scopeStack.top().isExecutable)
4626-
newFunctionDeclEnd = isFunctionHead(tok, "{:;");
4569+
newFunctionDeclEnd = TokenList::isFunctionHead(tok, "{:;");
46274570
else {
46284571
const Token* tokenLinkNext = tok->link()->next();
46294572
if (Token::simpleMatch(tokenLinkNext, ".")) { // skip trailing return type
@@ -4713,10 +4656,10 @@ void Tokenizer::setVarIdPass1()
47134656
if ((!scopeStack.top().isStructInit &&
47144657
(tok == list.front() ||
47154658
Token::Match(tok, "[;{}]") ||
4716-
(tok->str() == "(" && !scopeStack.top().isExecutable && isFunctionHead(tok,";:")) ||
4659+
(tok->str() == "(" && !scopeStack.top().isExecutable && TokenList::isFunctionHead(tok,";:")) ||
47174660
(tok->str() == "," && (!scopeStack.top().isExecutable || inlineFunction || !tok->previous()->varId())) ||
47184661
(tok->isName() && endsWith(tok->str(), ':')))) ||
4719-
(tok->str() == "(" && isFunctionHead(tok, "{"))) {
4662+
(tok->str() == "(" && TokenList::isFunctionHead(tok, "{"))) {
47204663

47214664
// No variable declarations in sizeof
47224665
if (Token::simpleMatch(tok->previous(), "sizeof (")) {
@@ -4764,7 +4707,7 @@ void Tokenizer::setVarIdPass1()
47644707
syntaxError(errTok);
47654708
}
47664709

4767-
if (tok->str() == "(" && isFunctionHead(tok, "{") && scopeStack.top().isExecutable)
4710+
if (tok->str() == "(" && TokenList::isFunctionHead(tok, "{") && scopeStack.top().isExecutable)
47684711
inlineFunction = true;
47694712

47704713
if (decl) {
@@ -5208,7 +5151,7 @@ void Tokenizer::setVarIdPass2()
52085151
// skip parentheses..
52095152
if (tok2->link()) {
52105153
if (tok2->str() == "(") {
5211-
Token *funcstart = const_cast<Token*>(isFunctionHead(tok2, "{"));
5154+
Token *funcstart = const_cast<Token*>(TokenList::isFunctionHead(tok2, "{"));
52125155
if (funcstart) {
52135156
setVarIdClassFunction(scopeName2 + classname, funcstart, funcstart->link(), thisClassVars, structMembers, mVarId);
52145157
tok2 = funcstart->link();
@@ -5264,7 +5207,7 @@ void Tokenizer::setVarIdPass2()
52645207
tok2 = tok2->linkAt(1);
52655208

52665209
// If this is a function implementation.. add it to funclist
5267-
Token * start = const_cast<Token *>(isFunctionHead(tok2, "{"));
5210+
Token * start = const_cast<Token *>(TokenList::isFunctionHead(tok2, "{"));
52685211
if (start) {
52695212
setVarIdClassFunction(classname, start, start->link(), thisClassVars, structMembers, mVarId);
52705213
}
@@ -6501,7 +6444,7 @@ void Tokenizer::removeMacrosInGlobalScope()
65016444
!Token::Match(tok2, "requires|namespace|class|struct|union|private:|protected:|public:"))
65026445
unknownMacroError(tok);
65036446

6504-
if (Token::Match(tok, "%type% (") && Token::Match(tok2, "%type% (") && !Token::Match(tok2, "noexcept|throw") && isFunctionHead(tok2->next(), ":;{"))
6447+
if (Token::Match(tok, "%type% (") && Token::Match(tok2, "%type% (") && !Token::Match(tok2, "noexcept|throw") && TokenList::isFunctionHead(tok2->next(), ":;{"))
65056448
unknownMacroError(tok);
65066449

65076450
// remove unknown macros before namespace|class|struct|union
@@ -6519,7 +6462,7 @@ void Tokenizer::removeMacrosInGlobalScope()
65196462

65206463
// replace unknown macros before foo(
65216464
/*
6522-
if (Token::Match(tok2, "%type% (") && isFunctionHead(tok2->next(), "{")) {
6465+
if (Token::Match(tok2, "%type% (") && TokenList::isFunctionHead(tok2->next(), "{")) {
65236466
std::string typeName;
65246467
for (const Token* tok3 = tok; tok3 != tok2; tok3 = tok3->next())
65256468
typeName += tok3->str();
@@ -7630,7 +7573,7 @@ bool Tokenizer::simplifyCAlternativeTokens()
76307573

76317574
for (Token *tok = list.front(); tok; tok = tok->next()) {
76327575
if (tok->str() == ")") {
7633-
if (const Token *end = isFunctionHead(tok, "{")) {
7576+
if (const Token *end = TokenList::isFunctionHead(tok, "{")) {
76347577
++executableScopeLevel;
76357578
tok = const_cast<Token *>(end);
76367579
continue;
@@ -9030,7 +8973,7 @@ void Tokenizer::simplifyFunctionTryCatch()
90308973
for (Token * tok = list.front(); tok; tok = tok->next()) {
90318974
if (!Token::Match(tok, "try {|:"))
90328975
continue;
9033-
if (!isFunctionHead(tok->previous(), "try"))
8976+
if (!TokenList::isFunctionHead(tok->previous(), "try"))
90348977
continue;
90358978

90368979
Token* tryStartToken = skipInitializerList(tok->next());
@@ -9472,7 +9415,7 @@ void Tokenizer::simplifyCPPAttribute()
94729415
head = skipCPPOrAlignAttribute(head)->next();
94739416
while (Token::Match(head, "%name%|::|*|&|<|>|,")) // skip return type
94749417
head = head->next();
9475-
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
9418+
if (head && head->str() == "(" && TokenList::isFunctionHead(head, "{|;")) {
94769419
head->previous()->isAttributeNoreturn(true);
94779420
}
94789421
} else if (Token::findsimplematch(tok->tokAt(2), "nodiscard", tok->link())) {
@@ -9481,7 +9424,7 @@ void Tokenizer::simplifyCPPAttribute()
94819424
head = skipCPPOrAlignAttribute(head)->next();
94829425
while (Token::Match(head, "%name%|::|*|&|<|>|,"))
94839426
head = head->next();
9484-
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
9427+
if (head && head->str() == "(" && TokenList::isFunctionHead(head, "{|;")) {
94859428
head->previous()->isAttributeNodiscard(true);
94869429
}
94879430
} else if ((hasMaybeUnusedUnderscores && Token::findsimplematch(tok->tokAt(2), "__maybe_unused__", tok->link()))
@@ -10048,9 +9991,9 @@ void Tokenizer::simplifyNamespaceStd()
100489991
if (Token::Match(tok->previous(), ".|::|namespace"))
100499992
continue;
100509993
if (Token::simpleMatch(tok->next(), "(")) {
10051-
if (isFunctionHead(tok->next(), "{"))
9994+
if (TokenList::isFunctionHead(tok->next(), "{"))
100529995
userFunctions.insert(tok->str());
10053-
else if (isFunctionHead(tok->next(), ";")) {
9996+
else if (TokenList::isFunctionHead(tok->next(), ";")) {
100549997
const Token *start = tok;
100559998
while (Token::Match(start->previous(), "%type%|*|&"))
100569999
start = start->previous();
@@ -10276,7 +10219,7 @@ void Tokenizer::createSymbolDatabase()
1027610219
bool Tokenizer::operatorEnd(const Token * tok)
1027710220
{
1027810221
if (tok && tok->str() == ")") {
10279-
if (isFunctionHead(tok, "{|;|?|:|["))
10222+
if (TokenList::isFunctionHead(tok, "{|;|?|:|["))
1028010223
return true;
1028110224

1028210225
tok = tok->next();
@@ -10298,7 +10241,7 @@ bool Tokenizer::operatorEnd(const Token * tok)
1029810241
tok = tok->link()->next();
1029910242
}
1030010243
} else if (Token::Match(tok, "%op% !!(") ||
10301-
(Token::Match(tok, "%op% (") && !isFunctionHead(tok->next(), "{")))
10244+
(Token::Match(tok, "%op% (") && !TokenList::isFunctionHead(tok->next(), "{")))
1030210245
break;
1030310246
else
1030410247
return false;
@@ -10469,7 +10412,7 @@ void Tokenizer::simplifyOverloadedOperators()
1046910412
++indent;
1047010413
else
1047110414
tok2 = tok2->link();
10472-
} else if (indent == 1 && Token::simpleMatch(tok2, "operator() (") && isFunctionHead(tok2->next(), ";{")) {
10415+
} else if (indent == 1 && Token::simpleMatch(tok2, "operator() (") && TokenList::isFunctionHead(tok2->next(), ";{")) {
1047310416
classNames.insert(tok->strAt(1));
1047410417
break;
1047510418
}

lib/tokenize.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -332,14 +332,6 @@ class CPPCHECKLIB Tokenizer {
332332
static std::string simplifyString(const std::string &source);
333333

334334
public:
335-
/**
336-
* is token pointing at function head?
337-
* @param tok A '(' or ')' token in a possible function head
338-
* @param endsWith string after function head
339-
* @return token matching with endsWith if syntax seems to be a function head else nullptr
340-
*/
341-
static const Token * isFunctionHead(const Token *tok, const std::string &endsWith);
342-
343335
bool hasIfdef(const Token *start, const Token *end) const;
344336

345337
bool isPacked(const Token * bodyStart) const;

0 commit comments

Comments
 (0)