Skip to content

Commit be6782d

Browse files
pfultz2danmar
authored andcommitted
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]; } ```
1 parent 888490f commit be6782d

3 files changed

Lines changed: 25 additions & 3 deletions

File tree

lib/astutils.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -772,16 +772,19 @@ bool isReturnScope(const Token * const endToken)
772772
!Token::findsimplematch(prev->link(), "break", prev)) {
773773
return true;
774774
}
775-
if (Token::simpleMatch(prev->link()->previous(), ") {") &&
776-
Token::simpleMatch(prev->link()->linkAt(-1)->previous(), "return (")) {
775+
if (Token::Match(prev->link()->astTop(), "return|throw"))
777776
return true;
778-
}
779777
if (Token::Match(prev->link()->previous(), "[;{}] {"))
780778
return isReturnScope(prev);
781779
} else if (Token::simpleMatch(prev, ";")) {
782780
// noreturn function
783781
if (Token::simpleMatch(prev->previous(), ") ;") && Token::Match(prev->linkAt(-1)->tokAt(-2), "[;{}] %name% ("))
784782
return true;
783+
if (Token::simpleMatch(prev->previous(), ") ;") && prev->previous()->link() &&
784+
Token::Match(prev->previous()->link()->astTop(), "return|throw"))
785+
return true;
786+
if (Token::Match(prev->previous()->astTop(), "return|throw"))
787+
return true;
785788
// return/goto statement
786789
prev = prev->previous();
787790
while (prev && !Token::Match(prev, ";|{|}|return|goto|throw|continue|break"))

test/testastutils.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,17 @@ class TestAstUtils : public TestFixture {
8585

8686
void isReturnScope() {
8787
ASSERT_EQUALS(true, isReturnScope("void f() { if (a) { return; } }", -2));
88+
ASSERT_EQUALS(true, isReturnScope("int f() { if (a) { return {}; } }", -2)); // #8891
89+
ASSERT_EQUALS(true, isReturnScope("std::string f() { if (a) { return std::string{}; } }", -2)); // #8891
90+
ASSERT_EQUALS(true, isReturnScope("std::string f() { if (a) { return std::string{\"\"}; } }", -2)); // #8891
8891
ASSERT_EQUALS(true, isReturnScope("void f() { if (a) { return (ab){0}; } }", -2)); // #7103
8992
ASSERT_EQUALS(false, isReturnScope("void f() { if (a) { return (ab){0}; } }", -4)); // #7103
9093
ASSERT_EQUALS(true, isReturnScope("void f() { if (a) { {throw new string(x);}; } }", -4)); // #7144
9194
ASSERT_EQUALS(true, isReturnScope("void f() { if (a) { {throw new string(x);}; } }", -2)); // #7144
95+
ASSERT_EQUALS(false, isReturnScope("void f() { [=]() { return data; }; }", -1));
96+
ASSERT_EQUALS(true, isReturnScope("auto f() { return [=]() { return data; }; }", -1));
97+
ASSERT_EQUALS(true, isReturnScope("auto f() { return [=]() { return data; }(); }", -1));
98+
ASSERT_EQUALS(false, isReturnScope("auto f() { [=]() { return data; }(); }", -1));
9299
}
93100

94101
bool isVariableChanged(const char code[], const char startPattern[], const char endPattern[]) {

test/teststl.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,18 @@ class TestStl : public TestFixture {
263263
" c.data();\n"
264264
"}\n");
265265
ASSERT_EQUALS("", errout.str());
266+
267+
checkNormal("std::string f(std::string x) {\n"
268+
" if (x.empty()) return {};\n"
269+
" x[0];\n"
270+
"}\n");
271+
ASSERT_EQUALS("", errout.str());
272+
273+
checkNormal("std::string f(std::string x) {\n"
274+
" if (x.empty()) return std::string{};\n"
275+
" x[0];\n"
276+
"}\n");
277+
ASSERT_EQUALS("", errout.str());
266278
}
267279

268280
void outOfBoundsIndexExpression() {

0 commit comments

Comments
 (0)