Fix FP 8891: Incorrect return scope when using uniform initialization

This fixes the FP in:

```cpp

std::string f(const std::string& data)
{
  if (data.empty())
    return {};

  data[0];
}
```
This commit is contained in:
Paul Fultz II 2018-12-14 18:31:10 +01:00 committed by Daniel Marjamäki
parent 888490fe6c
commit be6782d386
3 changed files with 25 additions and 3 deletions

View File

@ -772,16 +772,19 @@ bool isReturnScope(const Token * const endToken)
!Token::findsimplematch(prev->link(), "break", prev)) {
return true;
}
if (Token::simpleMatch(prev->link()->previous(), ") {") &&
Token::simpleMatch(prev->link()->linkAt(-1)->previous(), "return (")) {
if (Token::Match(prev->link()->astTop(), "return|throw"))
return true;
}
if (Token::Match(prev->link()->previous(), "[;{}] {"))
return isReturnScope(prev);
} else if (Token::simpleMatch(prev, ";")) {
// noreturn function
if (Token::simpleMatch(prev->previous(), ") ;") && Token::Match(prev->linkAt(-1)->tokAt(-2), "[;{}] %name% ("))
return true;
if (Token::simpleMatch(prev->previous(), ") ;") && prev->previous()->link() &&
Token::Match(prev->previous()->link()->astTop(), "return|throw"))
return true;
if (Token::Match(prev->previous()->astTop(), "return|throw"))
return true;
// return/goto statement
prev = prev->previous();
while (prev && !Token::Match(prev, ";|{|}|return|goto|throw|continue|break"))

View File

@ -85,10 +85,17 @@ private:
void isReturnScope() {
ASSERT_EQUALS(true, isReturnScope("void f() { if (a) { return; } }", -2));
ASSERT_EQUALS(true, isReturnScope("int f() { if (a) { return {}; } }", -2)); // #8891
ASSERT_EQUALS(true, isReturnScope("std::string f() { if (a) { return std::string{}; } }", -2)); // #8891
ASSERT_EQUALS(true, isReturnScope("std::string f() { if (a) { return std::string{\"\"}; } }", -2)); // #8891
ASSERT_EQUALS(true, isReturnScope("void f() { if (a) { return (ab){0}; } }", -2)); // #7103
ASSERT_EQUALS(false, isReturnScope("void f() { if (a) { return (ab){0}; } }", -4)); // #7103
ASSERT_EQUALS(true, isReturnScope("void f() { if (a) { {throw new string(x);}; } }", -4)); // #7144
ASSERT_EQUALS(true, isReturnScope("void f() { if (a) { {throw new string(x);}; } }", -2)); // #7144
ASSERT_EQUALS(false, isReturnScope("void f() { [=]() { return data; }; }", -1));
ASSERT_EQUALS(true, isReturnScope("auto f() { return [=]() { return data; }; }", -1));
ASSERT_EQUALS(true, isReturnScope("auto f() { return [=]() { return data; }(); }", -1));
ASSERT_EQUALS(false, isReturnScope("auto f() { [=]() { return data; }(); }", -1));
}
bool isVariableChanged(const char code[], const char startPattern[], const char endPattern[]) {

View File

@ -263,6 +263,18 @@ private:
" c.data();\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkNormal("std::string f(std::string x) {\n"
" if (x.empty()) return {};\n"
" x[0];\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkNormal("std::string f(std::string x) {\n"
" if (x.empty()) return std::string{};\n"
" x[0];\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void outOfBoundsIndexExpression() {