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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits