Fix #9250 (Regression: crash in gcc testsuite) (#2067)

* Fix #9250 (Regression: crash in gcc testsuite)

* fix cppcheck warning
This commit is contained in:
IOBYTE 2019-08-07 02:05:02 -04:00 committed by Daniel Marjamäki
parent cb0b057595
commit c6c50567cf
3 changed files with 65 additions and 44 deletions

View File

@ -3436,12 +3436,11 @@ void TemplateSimplifier::simplifyTemplates(
} }
} }
mTokenizer->calculateScopes();
unsigned int passCount = 0; unsigned int passCount = 0;
const unsigned int passCountMax = 10; const unsigned int passCountMax = 10;
for (; passCount < passCountMax; ++passCount) { for (; passCount < passCountMax; ++passCount) {
for (auto tok = mTokenizer->list.front(); tok; tok = tok->next()) tok->scopeInfo(nullptr);
mTokenizer->calculateScopes();
if (passCount) { if (passCount) {
// it may take more than one pass to simplify type aliases // it may take more than one pass to simplify type aliases
bool usingChanged = false; bool usingChanged = false;

View File

@ -2836,41 +2836,28 @@ void Tokenizer::simplifyCaseRange()
void Tokenizer::calculateScopes() void Tokenizer::calculateScopes()
{ {
for (auto tok = list.front(); tok; tok = tok->next())
tok->scopeInfo(nullptr);
std::string nextScopeNameAddition = ""; std::string nextScopeNameAddition = "";
std::shared_ptr<ScopeInfo2> primaryScope = std::make_shared<ScopeInfo2>("", nullptr);
if (!list.front()->scopeInfo()) { list.front()->scopeInfo(primaryScope);
std::shared_ptr<ScopeInfo2> primaryScope = std::make_shared<ScopeInfo2>("", list.back());
list.front()->scopeInfo(primaryScope);
if (Token::Match(list.front(), "using namespace %name% ::|<|;")) {
std::string usingNamespaceName = "";
for (const Token* namespaceNameToken = list.front()->tokAt(2); !Token::simpleMatch(namespaceNameToken, ";"); namespaceNameToken = namespaceNameToken->next()) {
usingNamespaceName += namespaceNameToken->str();
usingNamespaceName += " ";
}
if (usingNamespaceName.length() > 0) usingNamespaceName = usingNamespaceName.substr(0, usingNamespaceName.length() - 1);
list.front()->scopeInfo()->usingNamespaces.insert(usingNamespaceName);
} else if (Token::Match(list.front(), "namespace|class|struct|union %name% {|::|:|<")) {
for (Token* nameTok = list.front()->next(); nameTok && !Token::Match(nameTok, "{|:|<"); nameTok = nameTok->next()) {
nextScopeNameAddition.append(nameTok->str());
nextScopeNameAddition.append(" ");
}
if (nextScopeNameAddition.length() > 0) nextScopeNameAddition = nextScopeNameAddition.substr(0, nextScopeNameAddition.length() - 1);
}
}
for (Token* tok = list.front(); tok; tok = tok->next()) { for (Token* tok = list.front(); tok; tok = tok->next()) {
if (!tok->scopeInfo()) { if (tok == list.front() || !tok->scopeInfo()) {
tok->scopeInfo(tok->previous()->scopeInfo()); if (tok != list.front())
tok->scopeInfo(tok->previous()->scopeInfo());
if (Token::Match(tok, "using namespace %name% ::|<|;")) { if (Token::Match(tok, "using namespace %name% ::|<|;")) {
std::string usingNamespaceName = ""; std::string usingNamespaceName = "";
for (const Token* namespaceNameToken = tok->tokAt(2); !Token::simpleMatch(namespaceNameToken, ";"); namespaceNameToken = namespaceNameToken->next()) { for (const Token* namespaceNameToken = tok->tokAt(2);
!Token::simpleMatch(namespaceNameToken, ";");
namespaceNameToken = namespaceNameToken->next()) {
usingNamespaceName += namespaceNameToken->str(); usingNamespaceName += namespaceNameToken->str();
usingNamespaceName += " "; usingNamespaceName += " ";
} }
if (usingNamespaceName.length() > 0) usingNamespaceName = usingNamespaceName.substr(0, usingNamespaceName.length() - 1); if (usingNamespaceName.length() > 0)
usingNamespaceName = usingNamespaceName.substr(0, usingNamespaceName.length() - 1);
tok->scopeInfo()->usingNamespaces.insert(usingNamespaceName); tok->scopeInfo()->usingNamespaces.insert(usingNamespaceName);
} else if (Token::Match(tok, "namespace|class|struct|union %name% {|::|:|<")) { } else if (Token::Match(tok, "namespace|class|struct|union %name% {|::|:|<")) {
for (Token* nameTok = tok->next(); nameTok && !Token::Match(nameTok, "{|:"); nameTok = nameTok->next()) { for (Token* nameTok = tok->next(); nameTok && !Token::Match(nameTok, "{|:"); nameTok = nameTok->next()) {
@ -2881,7 +2868,8 @@ void Tokenizer::calculateScopes()
nextScopeNameAddition.append(nameTok->str()); nextScopeNameAddition.append(nameTok->str());
nextScopeNameAddition.append(" "); nextScopeNameAddition.append(" ");
} }
if (nextScopeNameAddition.length() > 0) nextScopeNameAddition = nextScopeNameAddition.substr(0, nextScopeNameAddition.length() - 1); if (nextScopeNameAddition.length() > 0)
nextScopeNameAddition = nextScopeNameAddition.substr(0, nextScopeNameAddition.length() - 1);
} }
if (Token::simpleMatch(tok, "{")) { if (Token::simpleMatch(tok, "{")) {
@ -2890,41 +2878,47 @@ void Tokenizer::calculateScopes()
while (Token::Match(tok1->previous(), "const|volatile|final|override|&|&&|noexcept")) while (Token::Match(tok1->previous(), "const|volatile|final|override|&|&&|noexcept"))
tok1 = tok1->previous(); tok1 = tok1->previous();
if (tok1 && tok1->previous() && tok1->strAt(-1) == ")") { if (tok1 && tok1->previous() && tok1->strAt(-1) == ")") {
bool member = true;
tok1 = tok1->linkAt(-1); tok1 = tok1->linkAt(-1);
if (Token::Match(tok1->previous(), "throw|noexcept")) { if (Token::Match(tok1->previous(), "throw|noexcept")) {
tok1 = tok1->previous(); tok1 = tok1->previous();
while (Token::Match(tok1->previous(), "const|volatile|final|override|&|&&|noexcept")) while (Token::Match(tok1->previous(), "const|volatile|final|override|&|&&|noexcept"))
tok1 = tok1->previous(); tok1 = tok1->previous();
if (tok1->strAt(-1) != ")") if (tok1->strAt(-1) != ")")
return; member = false;
} else if (Token::Match(tok->tokAt(-2), ":|, %name%")) { } else if (Token::Match(tok->tokAt(-2), ":|, %name%")) {
tok1 = tok1->tokAt(-2); tok1 = tok1->tokAt(-2);
if (tok1->strAt(-1) != ")") if (tok1->strAt(-1) != ")")
return; member = false;
} }
if (tok1->strAt(-1) == ">") if (member) {
tok1 = tok1->previous()->findOpeningBracket(); if (tok1->strAt(-1) == ">")
if (tok1 && Token::Match(tok1->tokAt(-3), "%name% :: %name%")) { tok1 = tok1->previous()->findOpeningBracket();
tok1 = tok1->tokAt(-2); if (tok1 && Token::Match(tok1->tokAt(-3), "%name% :: %name%")) {
std::string scope = tok1->strAt(-1);
while (Token::Match(tok1->tokAt(-2), ":: %name%")) {
scope = tok1->strAt(-3) + " :: " + scope;
tok1 = tok1->tokAt(-2); tok1 = tok1->tokAt(-2);
} std::string scope = tok1->strAt(-1);
while (Token::Match(tok1->tokAt(-2), ":: %name%")) {
scope = tok1->strAt(-3) + " :: " + scope;
tok1 = tok1->tokAt(-2);
}
if (!nextScopeNameAddition.empty() && !scope.empty()) nextScopeNameAddition += " :: "; if (!nextScopeNameAddition.empty() && !scope.empty())
nextScopeNameAddition += scope; nextScopeNameAddition += " :: ";
nextScopeNameAddition += scope;
}
} }
} }
// New scope is opening, record it here // New scope is opening, record it here
std::shared_ptr<ScopeInfo2> newScopeInfo = std::make_shared<ScopeInfo2>(tok->scopeInfo()->name, tok->link(), tok->scopeInfo()->usingNamespaces); std::shared_ptr<ScopeInfo2> newScopeInfo = std::make_shared<ScopeInfo2>(tok->scopeInfo()->name, tok->link(), tok->scopeInfo()->usingNamespaces);
if (newScopeInfo->name != "" && nextScopeNameAddition != "") newScopeInfo->name.append(" :: "); if (newScopeInfo->name != "" && nextScopeNameAddition != "")
newScopeInfo->name.append(" :: ");
newScopeInfo->name.append(nextScopeNameAddition); newScopeInfo->name.append(nextScopeNameAddition);
nextScopeNameAddition = ""; nextScopeNameAddition = "";
if (tok->link()) tok->link()->scopeInfo(tok->scopeInfo()); if (tok->link())
tok->link()->scopeInfo(tok->scopeInfo());
tok->scopeInfo(newScopeInfo); tok->scopeInfo(newScopeInfo);
} }
} }

View File

@ -169,6 +169,7 @@ private:
TEST_CASE(template129); TEST_CASE(template129);
TEST_CASE(template130); // #9246 TEST_CASE(template130); // #9246
TEST_CASE(template131); // #9249 TEST_CASE(template131); // #9249
TEST_CASE(template132); // #9250
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..}; TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..}; TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template) TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
@ -3129,6 +3130,33 @@ private:
} }
} }
void template132() { // #9250
const char code[] = "struct TrueFalse {\n"
" static constexpr bool v() { return true; }\n"
"};\n"
"int global;\n"
"template<typename T> int foo() {\n"
" __transaction_atomic noexcept(T::v()) { global += 1; }\n"
" return __transaction_atomic noexcept(T::v()) (global + 2);\n"
"}\n"
"int f1() {\n"
" return foo<TrueFalse>();\n"
"}";
const char exp[] = "struct TrueFalse { "
"static const bool v ( ) { return true ; } "
"} ; "
"int global ; "
"int foo<TrueFalse> ( ) ; "
"int f1 ( ) { "
"return foo<TrueFalse> ( ) ; "
"} "
"int foo<TrueFalse> ( ) { "
"__transaction_atomic noexcept ( TrueFalse :: v ( ) ) { global += 1 ; } "
"return __transaction_atomic noexcept ( TrueFalse :: v ( ) ) ( global + 2 ) ; "
"}";
ASSERT_EQUALS(exp, tok(code));
}
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..}; void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
const char code[] = "template <typename T> struct C {};\n" const char code[] = "template <typename T> struct C {};\n"
"template <typename T> struct S {a};\n" "template <typename T> struct S {a};\n"