diff --git a/clang/lib/Analysis/LifetimePsetBuilder.cpp b/clang/lib/Analysis/LifetimePsetBuilder.cpp index 4c7104c013389..80205cccac1f5 100644 --- a/clang/lib/Analysis/LifetimePsetBuilder.cpp +++ b/clang/lib/Analysis/LifetimePsetBuilder.cpp @@ -633,6 +633,16 @@ class PSetsBuilder : public ConstStmtVisitor { if (!Callee) return; + if (auto MCE = dyn_cast(CallE)) { + const CXXRecordDecl *RD = MCE->getRecordDecl(); + StringRef ClassName = RD->getName(); + if (RD->isInStdNamespace() && ClassName.endswith("unique_ptr") && + Callee->getName() == "release") { + // TODO: Print warning/note to suggest to not use release on std::unique_ptr + return; + } + } + /// Special case for assignment of Pointer into Pointer: copy pset if (auto *OC = dyn_cast(CallE)) { if (OC->getOperator() == OO_Equal && OC->getNumArgs() == 2 && diff --git a/clang/test/Sema/warn-lifetime-analysis.cpp b/clang/test/Sema/warn-lifetime-analysis.cpp index 43bee7fc80ae4..b0f8f2546dcc1 100644 --- a/clang/test/Sema/warn-lifetime-analysis.cpp +++ b/clang/test/Sema/warn-lifetime-analysis.cpp @@ -467,3 +467,30 @@ void b(basic_string &c) { c; // expected-warning {{expression result unused}} } } // namespace bug_report_66 +namespace bug_report_70 { +namespace std { +template +class unique_ptr { +public: + explicit unique_ptr(T *t); + T *release(); +}; +} // namespace std +template +class [[gsl::Owner]] unique_ptr { +public: + explicit unique_ptr(T *t); + T *release(); +}; +// A random class that models a private key. +class PrivateKey { +}; + +PrivateKey *getPrivateKeyStd() { + return std::unique_ptr(new PrivateKey()).release(); +} +PrivateKey *getPrivateKeyNonStd() { + return unique_ptr(new PrivateKey()).release(); // expected-warning {{returning a dangling pointer}} + // expected-note@-1 {{temporary was destroyed at the end of the full expression}} +} +} // namespace bug_report_70