rtrieu created this revision.
rtrieu added a subscriber: cfe-commits.

Track whether the initialization came from a GNU statement expression.  If it 
does, prevent the -Wpessiming-move warning from being emitted since the 
suggested fix can cause a compile error.

Fix for https://llvm.org/bugs/show_bug.cgi?id=25640

http://reviews.llvm.org/D15255

Files:
  include/clang/Sema/Initialization.h
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaInit.cpp
  test/SemaCXX/warn-pessmizing-move.cpp

Index: test/SemaCXX/warn-pessmizing-move.cpp
===================================================================
--- test/SemaCXX/warn-pessmizing-move.cpp
+++ test/SemaCXX/warn-pessmizing-move.cpp
@@ -227,3 +227,22 @@
     test2<B, A>();
   }
 }
+
+// Don't warn on GNU statement expressions.
+namespace GNU {
+  class A {};
+  class B {
+  public:
+    B();
+    B(B &&);
+  private:
+    B(const B &);
+  };
+
+  void test() {
+    A a = ({auto a = A(); std::move(a); });
+    B b = ({auto b = B(); std::move(b); });
+  }
+
+  auto b = std::move(B());
+}
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -2887,6 +2887,34 @@
   return false;
 }
 
+bool InitializedEntity::isGNUStatementExpression() const {
+  switch (getKind()) {
+  case EK_Result:
+    return LocAndNRVO.GNUStatementExpression;
+
+  case EK_Exception:
+  case EK_Variable:
+  case EK_Parameter:
+  case EK_Parameter_CF_Audited:
+  case EK_Member:
+  case EK_New:
+  case EK_Temporary:
+  case EK_CompoundLiteralInit:
+  case EK_Base:
+  case EK_Delegating:
+  case EK_ArrayElement:
+  case EK_VectorElement:
+  case EK_ComplexElement:
+  case EK_BlockElement:
+  case EK_LambdaCapture:
+  case EK_RelatedResult:
+    break;
+  }
+
+  return false;
+}
+
+
 unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
   assert(getParent() != this);
   unsigned Depth = getParent() ? getParent()->dumpImpl(OS) : 0;
@@ -6771,8 +6799,9 @@
 
   // Check for std::move on construction.
   if (const Expr *E = CurInit.get()) {
-    CheckMoveOnConstruction(S, E,
-                            Entity.getKind() == InitializedEntity::EK_Result);
+    if (!Entity.isGNUStatementExpression())
+      CheckMoveOnConstruction(S, E,
+                              Entity.getKind() == InitializedEntity::EK_Result);
   }
 
   return CurInit;
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -11149,11 +11149,8 @@
           LastExpr = rebuiltLastStmt;
         } else {
           LastExpr = PerformCopyInitialization(
-                            InitializedEntity::InitializeResult(LPLoc, 
-                                                                Ty,
-                                                                false),
-                                                   SourceLocation(),
-                                               LastExpr);
+              InitializedEntity::InitializeResult(LPLoc, Ty, false, true),
+              SourceLocation(), LastExpr);
         }
 
         if (LastExpr.isInvalid())
Index: include/clang/Sema/Initialization.h
===================================================================
--- include/clang/Sema/Initialization.h
+++ include/clang/Sema/Initialization.h
@@ -116,6 +116,10 @@
     /// \brief Whether the entity being initialized may end up using the
     /// named return value optimization (NRVO).
     bool NRVO;
+
+    /// \brief Whether the initialization is from the last expression of
+    /// a GNU statement expression.
+    bool GNUStatementExpression;
   };
 
   struct C {
@@ -169,11 +173,12 @@
   /// function, throwing an object, performing an explicit cast, or
   /// initializing a parameter for which there is no declaration.
   InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type,
-                    bool NRVO = false)
+                    bool NRVO = false, bool GNUStatementExpression = false)
     : Kind(Kind), Parent(nullptr), Type(Type), ManglingNumber(0)
   {
     LocAndNRVO.Location = Loc.getRawEncoding();
     LocAndNRVO.NRVO = NRVO;
+    LocAndNRVO.GNUStatementExpression = GNUStatementExpression;
   }
   
   /// \brief Create the initialization entity for a member subobject.
@@ -238,9 +243,11 @@
   }
 
   /// \brief Create the initialization entity for the result of a function.
-  static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
-                                            QualType Type, bool NRVO) {
-    return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO);
+  static InitializedEntity
+  InitializeResult(SourceLocation ReturnLoc, QualType Type, bool NRVO,
+                   bool GNUStatementExpression = false) {
+    return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO,
+                             GNUStatementExpression);
   }
 
   static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc,
@@ -364,6 +371,10 @@
   /// value optimization, which also applies to thrown objects.
   bool allowsNRVO() const;
 
+  /// \brief Determine whether this initializiation is from the final
+  /// expression of GNU statement expression.
+  bool isGNUStatementExpression() const;
+
   bool isParameterKind() const {
     return (getKind() == EK_Parameter  ||
             getKind() == EK_Parameter_CF_Audited);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to