diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2ca3d12edb77..fd90121bfe34 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(DRE->getDecl())) + return; + SourceLocation diagLoc; SourceRange diagRange; if (refVars.empty()) { @@ -6595,6 +6601,13 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, } else if (isa(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(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 ad27567fcd64..f6ea9b2a738a 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 @@ -20,3 +19,66 @@ void *&pointer() { } } +namespace LocalTemporary { + +template +class QMap { +public: + T value(const T &t = T()) const { + return t; + } +}; + +struct A {}; + +void test() { + QMap 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}} +} +}