Add support for namespace aliases and C++17 nested namespaces. (#1210)
* Add support for namespace aliases and C++17 nested namespaces. These are implemented as tokenizer simplifications so changes are not needed to the tokenizer and symbol database. * Fix codacy warning.
This commit is contained in:
parent
58ebc64b2f
commit
8b0b659965
111
lib/tokenize.cpp
111
lib/tokenize.cpp
|
@ -3577,6 +3577,12 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
||||||
if (_settings->terminated())
|
if (_settings->terminated())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// convert C++17 style nested namespaces to old style namespaces
|
||||||
|
simplifyNestedNamespace();
|
||||||
|
|
||||||
|
// simplify namespace aliases
|
||||||
|
simplifyNamespaceAliases();
|
||||||
|
|
||||||
// Remove [[attribute]]
|
// Remove [[attribute]]
|
||||||
simplifyCPPAttribute();
|
simplifyCPPAttribute();
|
||||||
|
|
||||||
|
@ -5617,6 +5623,8 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
|
||||||
continue;
|
continue;
|
||||||
if (isCPP11 && type0->str() == "using")
|
if (isCPP11 && type0->str() == "using")
|
||||||
continue;
|
continue;
|
||||||
|
if (isCPP() && type0->str() == "namespace")
|
||||||
|
continue;
|
||||||
|
|
||||||
bool isconst = false;
|
bool isconst = false;
|
||||||
bool isstatic = false;
|
bool isstatic = false;
|
||||||
|
@ -10162,3 +10170,106 @@ const Token *Tokenizer::findSQLBlockEnd(const Token *tokSQLStart)
|
||||||
|
|
||||||
return tokLastEnd;
|
return tokLastEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tokenizer::simplifyNestedNamespace()
|
||||||
|
{
|
||||||
|
if (!isCPP())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
|
if (Token::Match(tok, "namespace %name% ::") && tok->strAt(-1) != "using") {
|
||||||
|
Token * tok2 = tok->tokAt(2);
|
||||||
|
|
||||||
|
// validate syntax
|
||||||
|
while (Token::Match(tok2, ":: %name%"))
|
||||||
|
tok2 = tok2->tokAt(2);
|
||||||
|
|
||||||
|
if (!tok2 || tok2->str() != "{")
|
||||||
|
return; // syntax error
|
||||||
|
|
||||||
|
std::stack<Token *> links;
|
||||||
|
tok2 = tok->tokAt(2);
|
||||||
|
|
||||||
|
while (tok2->str() == "::") {
|
||||||
|
links.push(tok2);
|
||||||
|
tok2->str("{");
|
||||||
|
tok2->insertToken("namespace");
|
||||||
|
tok2 = tok2->tokAt(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
tok = tok2;
|
||||||
|
|
||||||
|
if (!links.empty() && tok2->str() == "{") {
|
||||||
|
tok2 = tok2->link();
|
||||||
|
while (!links.empty()) {
|
||||||
|
tok2->insertToken("}");
|
||||||
|
tok2 = tok2->next();
|
||||||
|
Token::createMutualLinks(links.top(), tok2);
|
||||||
|
links.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tokenizer::simplifyNamespaceAliases()
|
||||||
|
{
|
||||||
|
if (!isCPP())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int scope = 0;
|
||||||
|
|
||||||
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
|
if (tok->str() == "{")
|
||||||
|
scope++;
|
||||||
|
else if (tok->str() == "}")
|
||||||
|
scope--;
|
||||||
|
else if (Token::Match(tok, "namespace %name% =")) {
|
||||||
|
const std::string name(tok->next()->str());
|
||||||
|
Token * tokNameStart = tok->tokAt(3);
|
||||||
|
Token * tokNameEnd = tokNameStart;
|
||||||
|
|
||||||
|
while (tokNameEnd && tokNameEnd->next() && tokNameEnd->next()->str() != ";")
|
||||||
|
tokNameEnd = tokNameEnd->next();
|
||||||
|
|
||||||
|
if (!tokNameEnd)
|
||||||
|
return; // syntax error
|
||||||
|
|
||||||
|
int endScope = scope;
|
||||||
|
Token * tokLast = tokNameEnd->next();
|
||||||
|
Token * tokNext = tokLast->next();
|
||||||
|
Token * tok2 = tokNext;
|
||||||
|
|
||||||
|
while (tok2 && endScope >= scope) {
|
||||||
|
if (Token::simpleMatch(tok2, "{"))
|
||||||
|
endScope++;
|
||||||
|
else if (Token::simpleMatch(tok2, "}"))
|
||||||
|
endScope--;
|
||||||
|
else if (tok2->str() == name) {
|
||||||
|
tok2->str(tokNameStart->str());
|
||||||
|
Token * tok3 = tokNameStart;
|
||||||
|
while (tok3 != tokNameEnd) {
|
||||||
|
tok2->insertToken(tok3->next()->str());
|
||||||
|
tok2 = tok2->next();
|
||||||
|
tok3 = tok3->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tok2 = tok2->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tok->previous() && tokNext) {
|
||||||
|
Token::eraseTokens(tok->previous(), tokNext);
|
||||||
|
tok = tokNext->previous();
|
||||||
|
} else if (tok->previous()) {
|
||||||
|
Token::eraseTokens(tok->previous(), tokLast);
|
||||||
|
tok = tokLast;
|
||||||
|
} else if (tokNext) {
|
||||||
|
Token::eraseTokens(tok, tokNext);
|
||||||
|
tok->deleteThis();
|
||||||
|
} else {
|
||||||
|
Token::eraseTokens(tok, tokLast);
|
||||||
|
tok->deleteThis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -681,6 +681,16 @@ private:
|
||||||
* */
|
* */
|
||||||
bool simplifyStrlen();
|
bool simplifyStrlen();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert namespace aliases
|
||||||
|
*/
|
||||||
|
void simplifyNamespaceAliases();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert C++17 style nested namespace to older style
|
||||||
|
*/
|
||||||
|
void simplifyNestedNamespace();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare ternary operators with parentheses so that the AST can be created
|
* Prepare ternary operators with parentheses so that the AST can be created
|
||||||
* */
|
* */
|
||||||
|
|
|
@ -226,6 +226,8 @@ private:
|
||||||
TEST_CASE(simplifyArrayAddress); // Replace "&str[num]" => "(str + num)"
|
TEST_CASE(simplifyArrayAddress); // Replace "&str[num]" => "(str + num)"
|
||||||
TEST_CASE(simplifyCharAt);
|
TEST_CASE(simplifyCharAt);
|
||||||
TEST_CASE(simplifyOverride); // ticket #5069
|
TEST_CASE(simplifyOverride); // ticket #5069
|
||||||
|
TEST_CASE(simplifyNestedNamespace);
|
||||||
|
TEST_CASE(simplifyNamespaceAliases);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Native) {
|
std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Native) {
|
||||||
|
@ -3528,6 +3530,23 @@ private:
|
||||||
ASSERT_EQUALS("void fun ( ) { char override [ 2 ] = { 1 , 2 } ; doSomething ( override , 2 ) ; }",
|
ASSERT_EQUALS("void fun ( ) { char override [ 2 ] = { 1 , 2 } ; doSomething ( override , 2 ) ; }",
|
||||||
tok(code, true));
|
tok(code, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplifyNestedNamespace() {
|
||||||
|
ASSERT_EQUALS("namespace A { namespace B { namespace C { int i ; } } }", tok("namespace A::B::C { int i; }"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void simplifyNamespaceAliases() {
|
||||||
|
ASSERT_EQUALS(";",
|
||||||
|
tok("namespace ios = boost::iostreams;"));
|
||||||
|
ASSERT_EQUALS("boost :: iostreams :: istream foo ( \"foo\" ) ;",
|
||||||
|
tok("namespace ios = boost::iostreams; ios::istream foo(\"foo\");"));
|
||||||
|
ASSERT_EQUALS("boost :: iostreams :: istream foo ( \"foo\" ) ;",
|
||||||
|
tok("using namespace std; namespace ios = boost::iostreams; ios::istream foo(\"foo\");"));
|
||||||
|
ASSERT_EQUALS(";",
|
||||||
|
tok("using namespace std; namespace ios = boost::iostreams;"));
|
||||||
|
ASSERT_EQUALS("namespace NS { boost :: iostreams :: istream foo ( \"foo\" ) ; }",
|
||||||
|
tok("namespace NS { using namespace std; namespace ios = boost::iostreams; ios::istream foo(\"foo\"); }"));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestSimplifyTokens)
|
REGISTER_TEST(TestSimplifyTokens)
|
||||||
|
|
Loading…
Reference in New Issue