Don't produce a 'returning reference to local' warning if a lambda returns a
reference (or pointer) to a variable from the closure object or from the surrounding function scope. llvm-svn: 200494
This commit is contained in:
parent
0115b0879c
commit
40f08ebece
|
@ -4136,6 +4136,10 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
|||
case Stmt::DeclRefExprClass: {
|
||||
DeclRefExpr *DR = cast<DeclRefExpr>(E);
|
||||
|
||||
// If we leave the immediate function, the lifetime isn't about to end.
|
||||
if (DR->refersToEnclosingLocal())
|
||||
return 0;
|
||||
|
||||
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
|
||||
// If this is a reference variable, follow through to the expression that
|
||||
// it points to.
|
||||
|
@ -4292,6 +4296,10 @@ do {
|
|||
// local storage within the function, and if so, return the expression.
|
||||
DeclRefExpr *DR = cast<DeclRefExpr>(E);
|
||||
|
||||
// If we leave the immediate function, the lifetime isn't about to end.
|
||||
if (DR->refersToEnclosingLocal())
|
||||
return 0;
|
||||
|
||||
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
|
||||
// Check if it refers to itself, e.g. "int& i = i;".
|
||||
if (V == ParentDecl)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
|
||||
|
||||
int* ret_local() {
|
||||
int x = 1;
|
||||
|
@ -108,6 +108,11 @@ int* ret_cpp_const_cast(const int x) {
|
|||
return const_cast<int*>(&x); // expected-warning {{address of stack memory}}
|
||||
}
|
||||
|
||||
struct A { virtual ~A(); }; struct B : A {};
|
||||
A* ret_cpp_dynamic_cast(B b) {
|
||||
return dynamic_cast<A*>(&b); // expected-warning {{address of stack memory}}
|
||||
}
|
||||
|
||||
// PR 7999 - handle the case where a field is itself a reference.
|
||||
template <typename T> struct PR7999 {
|
||||
PR7999(T& t) : value(t) {}
|
||||
|
@ -137,5 +142,17 @@ namespace PR8774 {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: test case for dynamic_cast. clang does not yet have
|
||||
// support for C++ classes to write such a test case.
|
||||
// Don't warn about returning a local variable from a surrounding function if
|
||||
// we're within a lambda-expression.
|
||||
void ret_from_lambda() {
|
||||
int a;
|
||||
int &b = a;
|
||||
(void) [&]() -> int& { return a; };
|
||||
(void) [&]() -> int& { return b; };
|
||||
(void) [=]() mutable -> int& { return a; };
|
||||
(void) [=]() mutable -> int& { return b; };
|
||||
(void) [&]() -> int& { int a; return a; }; // expected-warning {{reference to stack}}
|
||||
(void) [=]() -> int& { int a; return a; }; // expected-warning {{reference to stack}}
|
||||
(void) [&]() -> int& { int &a = b; return a; };
|
||||
(void) [=]() mutable -> int& { int &a = b; return a; };
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue