[clang] 703038b - [Sema] Fix volatile check when testing if a return object can be implicitly moved

Arthur O'Dwyer via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 10 12:12:33 PST 2020


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


        


More information about the cfe-commits mailing list