diff options
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 13 | ||||
-rw-r--r-- | clang/test/SemaCXX/return-stack-addr-2.cpp | 64 |
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}} +} +} |