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

Reply via email to