[cfe-commits] r147839 - in /cfe/trunk: lib/AST/ExprConstant.cpp test/SemaCXX/constant-expression-cxx11.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon Jan 9 20:32:03 PST 2012


Author: rsmith
Date: Mon Jan  9 22:32:03 2012
New Revision: 147839

URL: http://llvm.org/viewvc/llvm-project?rev=147839&view=rev
Log:
PR11724: Implement evaluation for constexpr defaulted trivial union copy/move
constructors. These are a special case whose behavior cannot be modeled as a
user-written constructor.

Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=147839&r1=147838&r2=147839&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Jan  9 22:32:03 2012
@@ -1854,8 +1854,22 @@
     return EvaluateConstantExpression(Result, Info, This, (*I)->getInit());
   }
 
-  // Reserve space for the struct members.
+  // For a trivial copy or move constructor, perform an APValue copy. This is
+  // essential for unions, where the operations performed by the constructor
+  // cannot be represented by ctor-initializers.
   const CXXRecordDecl *RD = Definition->getParent();
+  if (Definition->isDefaulted() &&
+      ((Definition->isCopyConstructor() && RD->hasTrivialCopyConstructor()) ||
+       (Definition->isMoveConstructor() && RD->hasTrivialMoveConstructor()))) {
+    LValue RHS;
+    RHS.setFrom(ArgValues[0]);
+    CCValue Value;
+    return HandleLValueToRValueConversion(Info, Args[0], Args[0]->getType(),
+                                          RHS, Value) &&
+           CheckConstantExpression(Info, CallExpr, Value, Result);
+  }
+
+  // Reserve space for the struct members.
   if (!RD->isUnion() && Result.isUninit())
     Result = APValue(APValue::UninitStruct(), RD->getNumBases(),
                      std::distance(RD->field_begin(), RD->field_end()));
@@ -3073,7 +3087,7 @@
   if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
     return false;
 
-  // FIXME: Elide the copy/move construction wherever we can.
+  // Avoid materializing a temporary for an elidable copy/move constructor.
   if (E->isElidable() && !ZeroInit)
     if (const MaterializeTemporaryExpr *ME
           = dyn_cast<MaterializeTemporaryExpr>(E->getArg(0)))

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=147839&r1=147838&r2=147839&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Mon Jan  9 22:32:03 2012
@@ -726,6 +726,12 @@
 static_assert(*(&(u[1].b) + 1 + 1) == 3, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element 2 of non-array object}}
 static_assert((&(u[1]) + 1 + 1)->b == 3, "");
 
+// Make sure we handle trivial copy constructors for unions.
+constexpr U x = {42};
+constexpr U y = x;
+static_assert(y.a == 42, "");
+static_assert(y.b == 42, ""); // expected-error {{constant expression}} expected-note {{'b' of union with active member 'a'}}
+
 }
 
 namespace MemberPointer {





More information about the cfe-commits mailing list