Author: Yang Fan Date: 2020-11-10T15:11:07-05:00 New Revision: 703038b35a864d06e1926237c1568a430417b0b4
URL: https://github.com/llvm/llvm-project/commit/703038b35a864d06e1926237c1568a430417b0b4 DIFF: https://github.com/llvm/llvm-project/commit/703038b35a864d06e1926237c1568a430417b0b4.diff LOG: [Sema] Fix volatile check when testing if a return object can be implicitly moved In C++11 standard, to become implicitly movable, the expression in return statement should be a non-volatile automatic object. CWG1579 changed the rule to require that the expression only needs to be an automatic object. C++14 standard and C++17 standard kept this rule unchanged. C++20 standard changed the rule back to require the expression be a non-volatile automatic object. This should be a typo in standards, and VD should be non-volatile. Differential Revision: https://reviews.llvm.org/D88295 Added: clang/test/CXX/class/class.init/class.copy.elision/p1.cpp Modified: clang/lib/Sema/SemaStmt.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 2672cadfa421..195121e1e256 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3074,12 +3074,13 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD, // variable will no longer be used. if (VD->hasAttr<BlocksAttr>()) 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<AlignedAttr>() && 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 index 000000000000..457feef0643d --- /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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits