forked from OSchip/llvm-project
Fix two false positives in -Wreturn-stack-address
If the return type is a pointer and the function returns the reference to a pointer, don't warn since only the value is returned, not the reference. If a reference function parameter appears in the reference chain, don't warn since binding happens at the caller scope, so addresses returned are not to local stack. This includes default arguments as well. llvm-svn: 277889
This commit is contained in:
parent
9e91c28b71
commit
81b6c561ea
|
@ -6572,6 +6572,12 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
|
|||
if (!stackE)
|
||||
return; // Nothing suspicious was found.
|
||||
|
||||
// Parameters are initalized in the calling scope, so taking the address
|
||||
// of a parameter reference doesn't need a warning.
|
||||
for (auto *DRE : refVars)
|
||||
if (isa<ParmVarDecl>(DRE->getDecl()))
|
||||
return;
|
||||
|
||||
SourceLocation diagLoc;
|
||||
SourceRange diagRange;
|
||||
if (refVars.empty()) {
|
||||
|
@ -6595,6 +6601,13 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
|
|||
} else if (isa<AddrLabelExpr>(stackE)) { // address of label.
|
||||
S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
|
||||
} else { // local temporary.
|
||||
// If there is an LValue->RValue conversion, then the value of the
|
||||
// reference type is used, not the reference.
|
||||
if (auto *ICE = dyn_cast<ImplicitCastExpr>(RetValExp)) {
|
||||
if (ICE->getCastKind() == CK_LValueToRValue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
S.Diag(diagLoc, diag::warn_ret_local_temp_addr_ref)
|
||||
<< lhsType->isReferenceType() << diagRange;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -std=c++11 %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
namespace PR26599 {
|
||||
template <typename>
|
||||
|
@ -20,3 +19,66 @@ void *&pointer() {
|
|||
}
|
||||
}
|
||||
|
||||
namespace LocalTemporary {
|
||||
|
||||
template <class T>
|
||||
class QMap {
|
||||
public:
|
||||
T value(const T &t = T()) const {
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
||||
struct A {};
|
||||
|
||||
void test() {
|
||||
QMap<A *> map;
|
||||
map.value();
|
||||
}
|
||||
|
||||
typedef int* ptr;
|
||||
ptr int1(const ptr &p = ptr()) {
|
||||
return (p);
|
||||
}
|
||||
|
||||
ptr int2(const ptr &p = nullptr) {
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr int3() {
|
||||
const ptr &p = ptr();
|
||||
return p;
|
||||
}
|
||||
|
||||
const int *int4(const int &x = 5) {
|
||||
return &x;
|
||||
}
|
||||
|
||||
const int *int5(const int &x) {
|
||||
return &x;
|
||||
}
|
||||
|
||||
const int *int6() {
|
||||
const int &x = 11; //expected-note{{binding reference variable 'x' here}}
|
||||
return &x; //expected-warning{{returning address of local temporary object}}
|
||||
}
|
||||
|
||||
const int *int7(int x) {
|
||||
const int &x2 = x; // expected-note{{binding reference variable 'x2' here}}
|
||||
const int &x3 = x2;
|
||||
return &x2; // expected-warning{{address of stack memory associated with local variable 'x' returned}}
|
||||
}
|
||||
|
||||
const int *int8(const int &x = 5) {
|
||||
const int &x2 = x;
|
||||
const int &x3 = x2;
|
||||
return &x2;
|
||||
}
|
||||
|
||||
const int *int9() {
|
||||
const int &x = 5; // expected-note{{binding reference variable 'x' here}}
|
||||
const int &x2 = x; // expected-note{{binding reference variable 'x2' here}}
|
||||
const int &x3 = x2;
|
||||
return &x2; // expected-warning{{returning address of local temporary object}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue