[clang] 48587f3 - [clang] Add new warning: not eliding copy on return (missed NRVO) (#139973)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 16 11:47:56 PDT 2025
Author: Grigory Pastukhov
Date: 2025-05-16T15:47:53-03:00
New Revision: 48587f30d63689816f3d5a1d199dba42ff332247
URL: https://github.com/llvm/llvm-project/commit/48587f30d63689816f3d5a1d199dba42ff332247
DIFF: https://github.com/llvm/llvm-project/commit/48587f30d63689816f3d5a1d199dba42ff332247.diff
LOG: [clang] Add new warning: not eliding copy on return (missed NRVO) (#139973)
Added:
clang/test/SemaCXX/warn-nrvo.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaDecl.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0c12091a90add..537f29521fb7f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -313,6 +313,8 @@ New Compiler Flags
- New option ``-ftime-report-json`` added which outputs the same timing data as ``-ftime-report`` but formatted as JSON.
+- New option ``-Wnrvo`` added and disabled by default to warn about missed NRVO opportunites.
+
Deprecated Compiler Flags
-------------------------
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f0bd5a1174020..d78a757c72e4a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12445,6 +12445,10 @@ def warn_zero_as_null_pointer_constant : Warning<
"zero as null pointer constant">,
InGroup<DiagGroup<"zero-as-null-pointer-constant">>, DefaultIgnore;
+def warn_not_eliding_copy_on_return : Warning<
+ "not eliding copy on return">,
+ InGroup<DiagGroup<"nrvo">>, DefaultIgnore;
+
def err_nullability_cs_multilevel : Error<
"nullability keyword %0 cannot be applied to multi-level pointer type %1">;
def note_nullability_type_specifier : Note<
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a7d59ec232b64..6dae243b520f0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -16093,8 +16093,11 @@ void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) {
if (const VarDecl *NRVOCandidate = Returns[I]->getNRVOCandidate()) {
- if (!NRVOCandidate->isNRVOVariable())
+ if (!NRVOCandidate->isNRVOVariable()) {
+ Diag(Returns[I]->getRetValue()->getExprLoc(),
+ diag::warn_not_eliding_copy_on_return);
Returns[I]->setNRVOCandidate(nullptr);
+ }
}
}
}
diff --git a/clang/test/SemaCXX/warn-nrvo.cpp b/clang/test/SemaCXX/warn-nrvo.cpp
new file mode 100644
index 0000000000000..55bbdbd3e6e40
--- /dev/null
+++ b/clang/test/SemaCXX/warn-nrvo.cpp
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -fsyntax-only -Wnrvo -Wno-return-mismatch -verify %s
+struct MyClass {
+ int value;
+ int c;
+ MyClass(int v) : value(v), c(0) {}
+ MyClass(const MyClass& other) : value(other.value) { c++; }
+};
+
+MyClass create_object(bool condition) {
+ MyClass obj1(1);
+ MyClass obj2(2);
+ if (condition) {
+ return obj1; // expected-warning{{not eliding copy on return}}
+ }
+ return obj2; // expected-warning{{not eliding copy on return}}
+}
+
+MyClass create_object2(){
+ MyClass obj(1);
+ return obj; // no warning
+}
+
+template<typename T>
+T create_object3(){
+ T obj(1);
+ return obj; // no warning
+}
+
+// Known issue: if a function template uses a
+// deduced return type (i.e. auto or decltype(auto)),
+// then NRVO is not applied for any instantiation of
+// that function template
+// (see https://github.com/llvm/llvm-project/issues/95280).
+template<typename T>
+auto create_object4(){
+ T obj(1);
+ return obj; // expected-warning{{not eliding copy on return}}
+}
+
+template<bool F>
+MyClass create_object5(){
+ MyClass obj1(1);
+ if constexpr (F){
+ MyClass obj2(2);
+ return obj2; // no warning
+ }
+ // Missed NRVO optimization by clang
+ return obj1; // expected-warning{{not eliding copy on return}}
+}
+
+constexpr bool Flag = false;
+
+MyClass create_object6(){
+ MyClass obj1(1);
+ if constexpr (Flag){
+ MyClass obj2(2);
+ return obj2; // expected-warning{{not eliding copy on return}}
+ }
+ return obj1; // no warning
+}
+
+void create_object7(){
+ if constexpr (Flag){
+ MyClass obj1(1);
+ return obj1; // no warning
+ }
+}
+
+void init_templates(){
+ create_object3<MyClass>(); // no warning
+ create_object4<MyClass>(); // expected-note {{in instantiation of function template specialization 'create_object4<MyClass>' requested here}}
+ create_object5<false>(); // expected-note {{in instantiation of function template specialization 'create_object5<false>' requested here}}
+}
More information about the cfe-commits
mailing list