diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3074,12 +3074,13 @@ // variable will no longer be used. if (VD->hasAttr()) return false; + // ...non-volatile... + if (VD->getType().isVolatileQualified()) + return false; + if (CESK & CES_AllowDifferentTypes) return true; - // ...non-volatile... - if (VD->getType().isVolatileQualified()) return false; - // Variables with higher required alignment than their type's ABI // alignment cannot use NRVO. if (!VD->getType()->isDependentType() && VD->hasAttr() && diff --git a/clang/test/CXX/class/class.init/class.copy.elision/p1.cpp b/clang/test/CXX/class/class.init/class.copy.elision/p1.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CXX/class/class.init/class.copy.elision/p1.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++20 -emit-llvm -triple x86_64-unknown-linux-gnu -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -emit-llvm -triple x86_64-unknown-linux-gnu -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++14 -emit-llvm -triple x86_64-unknown-linux-gnu -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm -triple x86_64-unknown-linux-gnu -o - %s | FileCheck %s + +// - volatile object in return statement don't match the rule for using move +// operation instead of copy operation. Thus should call the copy constructor +// A(const volatile A &). +// +// - volatile object in return statement also don't match the rule for copy +// elision. Thus the copy constructor A(const volatile A &) cannot be elided. +namespace test_volatile { +class A { +public: + A() {} + ~A() {} + A(const volatile A &); + A(volatile A &&); +}; + +A test() { + volatile A a_copy; + // CHECK: call void @_ZN13test_volatile1AC1ERVKS0_ + return a_copy; +} +} // namespace test_volatile