t.p.northover created this revision. Herald added a subscriber: mcrosier. When trying to switch to C++14 by default, some extra expressions become constexpr and this is one case we can't handle.
Technically I believe weakening the assert would be enough to fix the problem, but defaulted default constructors are extremely close to being allowed through which would lead to incorrect code (all of isDefaulted, isTrivial and hasFields contribute to the exclusion, as well as the fact that unions don't have default constructors). So I decided to explicitly check that we are dealing with a copy/move before executing that block. https://reviews.llvm.org/D33610 Files: clang/lib/AST/ExprConstant.cpp clang/test/CodeGenCXX/constructor-direct-call.cpp Index: clang/test/CodeGenCXX/constructor-direct-call.cpp =================================================================== --- clang/test/CodeGenCXX/constructor-direct-call.cpp +++ clang/test/CodeGenCXX/constructor-direct-call.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple i686-pc-mingw32 -fms-extensions -Wmicrosoft %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686-pc-mingw32 -fms-extensions -Wmicrosoft %s -emit-llvm -o - -std=gnu++11| FileCheck %s class Test1 { public: Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -4184,18 +4184,27 @@ CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues.data()); + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee); + bool IsCopyOrMove = MD && MD->isCopyAssignmentOperator(); + IsCopyOrMove |= MD && MD->isMoveAssignmentOperator(); + + // We support explicit constructor calls as an MS extension. These can be + // constexpr by C++11 rules. + auto CD = dyn_cast_or_null<CXXConstructorDecl>(MD); + IsCopyOrMove |= CD && CD->isCopyConstructor(); + IsCopyOrMove |= CD && CD->isMoveConstructor(); + // For a trivial copy or move assignment, perform an APValue copy. This is // essential for unions, where the operations performed by the assignment // operator cannot be represented as statements. // // Skip this for non-union classes with no fields; in that case, the defaulted // copy/move does not actually read the object. - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee); - if (MD && MD->isDefaulted() && + if (MD && MD->isDefaulted() && IsCopyOrMove && (MD->getParent()->isUnion() || (MD->isTrivial() && hasFields(MD->getParent())))) { - assert(This && - (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())); + assert(This); + LValue RHS; RHS.setFrom(Info.Ctx, ArgValues[0]); APValue RHSValue;
Index: clang/test/CodeGenCXX/constructor-direct-call.cpp =================================================================== --- clang/test/CodeGenCXX/constructor-direct-call.cpp +++ clang/test/CodeGenCXX/constructor-direct-call.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple i686-pc-mingw32 -fms-extensions -Wmicrosoft %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686-pc-mingw32 -fms-extensions -Wmicrosoft %s -emit-llvm -o - -std=gnu++11| FileCheck %s class Test1 { public: Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -4184,18 +4184,27 @@ CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues.data()); + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee); + bool IsCopyOrMove = MD && MD->isCopyAssignmentOperator(); + IsCopyOrMove |= MD && MD->isMoveAssignmentOperator(); + + // We support explicit constructor calls as an MS extension. These can be + // constexpr by C++11 rules. + auto CD = dyn_cast_or_null<CXXConstructorDecl>(MD); + IsCopyOrMove |= CD && CD->isCopyConstructor(); + IsCopyOrMove |= CD && CD->isMoveConstructor(); + // For a trivial copy or move assignment, perform an APValue copy. This is // essential for unions, where the operations performed by the assignment // operator cannot be represented as statements. // // Skip this for non-union classes with no fields; in that case, the defaulted // copy/move does not actually read the object. - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee); - if (MD && MD->isDefaulted() && + if (MD && MD->isDefaulted() && IsCopyOrMove && (MD->getParent()->isUnion() || (MD->isTrivial() && hasFields(MD->getParent())))) { - assert(This && - (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())); + assert(This); + LValue RHS; RHS.setFrom(Info.Ctx, ArgValues[0]); APValue RHSValue;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits