[clang] ad18665 - PR45087: Fix check for emptiness when determining whether a trivial copy
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 3 15:57:56 PST 2020
Author: Richard Smith
Date: 2020-03-03T15:57:48-08:00
New Revision: ad18665e377824fd545ca81117b4953e60e2823c
URL: https://github.com/llvm/llvm-project/commit/ad18665e377824fd545ca81117b4953e60e2823c
DIFF: https://github.com/llvm/llvm-project/commit/ad18665e377824fd545ca81117b4953e60e2823c.diff
LOG: PR45087: Fix check for emptiness when determining whether a trivial copy
operation needs to read from its operand.
Added:
Modified:
clang/lib/AST/ExprConstant.cpp
clang/test/SemaCXX/constant-expression-cxx11.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9a31b64eedda..1028ab96bfd2 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3047,15 +3047,22 @@ static void expandArray(APValue &Array, unsigned Index) {
/// is trivial. Note that this is never true for a union type with fields
/// (because the copy always "reads" the active member) and always true for
/// a non-class type.
+static bool isReadByLvalueToRvalueConversion(const CXXRecordDecl *RD);
static bool isReadByLvalueToRvalueConversion(QualType T) {
CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
- if (!RD || (RD->isUnion() && !RD->field_empty()))
- return true;
+ return !RD || isReadByLvalueToRvalueConversion(RD);
+}
+static bool isReadByLvalueToRvalueConversion(const CXXRecordDecl *RD) {
+ // FIXME: A trivial copy of a union copies the object representation, even if
+ // the union is empty.
+ if (RD->isUnion())
+ return !RD->field_empty();
if (RD->isEmpty())
return false;
for (auto *Field : RD->fields())
- if (isReadByLvalueToRvalueConversion(Field->getType()))
+ if (!Field->isUnnamedBitfield() &&
+ isReadByLvalueToRvalueConversion(Field->getType()))
return true;
for (auto &BaseSpec : RD->bases())
@@ -5460,22 +5467,6 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
return true;
}
-/// Determine if a class has any fields that might need to be copied by a
-/// trivial copy or move operation.
-static bool hasFields(const CXXRecordDecl *RD) {
- if (!RD || RD->isEmpty())
- return false;
- for (auto *FD : RD->fields()) {
- if (FD->isUnnamedBitfield())
- continue;
- return true;
- }
- for (auto &Base : RD->bases())
- if (hasFields(Base.getType()->getAsCXXRecordDecl()))
- return true;
- return false;
-}
-
namespace {
typedef SmallVector<APValue, 8> ArgVector;
}
@@ -5546,7 +5537,8 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee);
if (MD && MD->isDefaulted() &&
(MD->getParent()->isUnion() ||
- (MD->isTrivial() && hasFields(MD->getParent())))) {
+ (MD->isTrivial() &&
+ isReadByLvalueToRvalueConversion(MD->getParent())))) {
assert(This &&
(MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));
LValue RHS;
@@ -5633,7 +5625,8 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
// actually read them.
if (Definition->isDefaulted() && Definition->isCopyOrMoveConstructor() &&
(Definition->getParent()->isUnion() ||
- (Definition->isTrivial() && hasFields(Definition->getParent())))) {
+ (Definition->isTrivial() &&
+ isReadByLvalueToRvalueConversion(Definition->getParent())))) {
LValue RHS;
RHS.setFrom(Info.Ctx, ArgValues[0]);
return handleLValueToRValueConversion(
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 44b636a5b808..4c0cf109bee0 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -600,6 +600,10 @@ namespace CopyCtor {
constexpr B c = b;
static_assert(c.arr[2] == 3, "");
static_assert(c.arr[7] == 0, "");
+
+ // OK: the copy ctor for X doesn't read any members.
+ struct X { struct Y {} y; } x1;
+ constexpr X x2 = x1;
}
constexpr int selfref[2][2][2] = {
More information about the cfe-commits
mailing list