summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2016-08-05 23:24:47 +0000
committerRichard Trieu <rtrieu@google.com>2016-08-05 23:24:47 +0000
commit81b6c561eaeb2a48318523a037e6903d34f5fec3 (patch)
tree2573ed1a4e12c1561d4a9135555a2065ccbceddf
parent9e91c28b7121f726b3ee62bd5d17abb9bfe6841a (diff)
downloadbcm5719-llvm-81b6c561eaeb2a48318523a037e6903d34f5fec3.tar.gz
bcm5719-llvm-81b6c561eaeb2a48318523a037e6903d34f5fec3.zip
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
-rw-r--r--clang/lib/Sema/SemaChecking.cpp13
-rw-r--r--clang/test/SemaCXX/return-stack-addr-2.cpp64
2 files changed, 76 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 2ca3d12edb7..fd90121bfe3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -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;
}
diff --git a/clang/test/SemaCXX/return-stack-addr-2.cpp b/clang/test/SemaCXX/return-stack-addr-2.cpp
index ad27567fcd6..f6ea9b2a738 100644
--- a/clang/test/SemaCXX/return-stack-addr-2.cpp
+++ b/clang/test/SemaCXX/return-stack-addr-2.cpp
@@ -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}}
+}
+}
OpenPOWER on IntegriCloud