r225756 - Extend the self move warning to record types.

Richard Trieu rtrieu at google.com
Mon Jan 12 18:32:03 PST 2015


Author: rtrieu
Date: Mon Jan 12 20:32:02 2015
New Revision: 225756

URL: http://llvm.org/viewvc/llvm-project?rev=225756&view=rev
Log:
Extend the self move warning to record types.

Move the logic for checking self moves into SemaChecking and add that function
to Sema since it is now used in multiple places.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/warn-self-move.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=225756&r1=225755&r2=225756&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jan 12 20:32:02 2015
@@ -3326,6 +3326,10 @@ public:
   void DiagnoseEmptyLoopBody(const Stmt *S,
                              const Stmt *PossibleBody);
 
+  /// Warn if a value is moved to itself.
+  void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
+                        SourceLocation OpLoc);
+
   ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
     return DelayedDiagnostics.push(pool);
   }

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=225756&r1=225755&r2=225756&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Jan 12 20:32:02 2015
@@ -8325,6 +8325,96 @@ void Sema::DiagnoseEmptyLoopBody(const S
   }
 }
 
+//===--- CHECK: Warn on self move with std::move. -------------------------===//
+
+/// DiagnoseSelfMove - Emits a warning if a value is moved to itself.
+void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
+                             SourceLocation OpLoc) {
+
+  if (Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess, OpLoc))
+    return;
+
+  if (!ActiveTemplateInstantiations.empty())
+    return;
+
+  // Strip parens and casts away.
+  LHSExpr = LHSExpr->IgnoreParenImpCasts();
+  RHSExpr = RHSExpr->IgnoreParenImpCasts();
+
+  // Check for a call expression
+  const CallExpr *CE = dyn_cast<CallExpr>(RHSExpr);
+  if (!CE || CE->getNumArgs() != 1)
+    return;
+
+  // Check for a call to std::move
+  const FunctionDecl *FD = CE->getDirectCallee();
+  if (!FD || !FD->isInStdNamespace() || !FD->getIdentifier() ||
+      !FD->getIdentifier()->isStr("move"))
+    return;
+
+  // Get argument from std::move
+  RHSExpr = CE->getArg(0);
+
+  const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
+  const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);
+
+  // Two DeclRefExpr's, check that the decls are the same.
+  if (LHSDeclRef && RHSDeclRef) {
+    if (!LHSDeclRef->getDecl() || !RHSDeclRef->getDecl())
+      return;
+    if (LHSDeclRef->getDecl()->getCanonicalDecl() !=
+        RHSDeclRef->getDecl()->getCanonicalDecl())
+      return;
+
+    Diag(OpLoc, diag::warn_self_move) << LHSExpr->getType()
+                                        << LHSExpr->getSourceRange()
+                                        << RHSExpr->getSourceRange();
+    return;
+  }
+
+  // Member variables require a different approach to check for self moves.
+  // MemberExpr's are the same if every nested MemberExpr refers to the same
+  // Decl and that the base Expr's are DeclRefExpr's with the same Decl or
+  // the base Expr's are CXXThisExpr's.
+  const Expr *LHSBase = LHSExpr;
+  const Expr *RHSBase = RHSExpr;
+  const MemberExpr *LHSME = dyn_cast<MemberExpr>(LHSExpr);
+  const MemberExpr *RHSME = dyn_cast<MemberExpr>(RHSExpr);
+  if (!LHSME || !RHSME)
+    return;
+
+  while (LHSME && RHSME) {
+    if (LHSME->getMemberDecl()->getCanonicalDecl() !=
+        RHSME->getMemberDecl()->getCanonicalDecl())
+      return;
+
+    LHSBase = LHSME->getBase();
+    RHSBase = RHSME->getBase();
+    LHSME = dyn_cast<MemberExpr>(LHSBase);
+    RHSME = dyn_cast<MemberExpr>(RHSBase);
+  }
+
+  LHSDeclRef = dyn_cast<DeclRefExpr>(LHSBase);
+  RHSDeclRef = dyn_cast<DeclRefExpr>(RHSBase);
+  if (LHSDeclRef && RHSDeclRef) {
+    if (!LHSDeclRef->getDecl() || !RHSDeclRef->getDecl())
+      return;
+    if (LHSDeclRef->getDecl()->getCanonicalDecl() !=
+        RHSDeclRef->getDecl()->getCanonicalDecl())
+      return;
+
+    Diag(OpLoc, diag::warn_self_move) << LHSExpr->getType()
+                                        << LHSExpr->getSourceRange()
+                                        << RHSExpr->getSourceRange();
+    return;
+  }
+
+  if (isa<CXXThisExpr>(LHSBase) && isa<CXXThisExpr>(RHSBase))
+    Diag(OpLoc, diag::warn_self_move) << LHSExpr->getType()
+                                        << LHSExpr->getSourceRange()
+                                        << RHSExpr->getSourceRange();
+}
+
 //===--- Layout compatibility ----------------------------------------------//
 
 namespace {

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=225756&r1=225755&r2=225756&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jan 12 20:32:02 2015
@@ -9380,90 +9380,6 @@ static inline UnaryOperatorKind ConvertT
   return Opc;
 }
 
-/// DiagnoseSelfMove - Emits a warning if a value is moved to itself.
-static void DiagnoseSelfMove(Sema &S, const Expr *LHSExpr, const Expr *RHSExpr,
-                             SourceLocation OpLoc) {
-  if (!S.ActiveTemplateInstantiations.empty())
-    return;
-
-  // Strip parens and casts away.
-  LHSExpr = LHSExpr->IgnoreParenImpCasts();
-  RHSExpr = RHSExpr->IgnoreParenImpCasts();
-
-  // Check for a call expression
-  const CallExpr *CE = dyn_cast<CallExpr>(RHSExpr);
-  if (!CE || CE->getNumArgs() != 1)
-    return;
-
-  // Check for a call to std::move
-  const FunctionDecl *FD = CE->getDirectCallee();
-  if (!FD || !FD->isInStdNamespace() || !FD->getIdentifier() ||
-      !FD->getIdentifier()->isStr("move"))
-    return;
-
-  // Get argument from std::move
-  RHSExpr = CE->getArg(0);
-
-  const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
-  const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);
-
-  // Two DeclRefExpr's, check that the decls are the same.
-  if (LHSDeclRef && RHSDeclRef) {
-    if (!LHSDeclRef->getDecl() || !RHSDeclRef->getDecl())
-      return;
-    if (LHSDeclRef->getDecl()->getCanonicalDecl() !=
-        RHSDeclRef->getDecl()->getCanonicalDecl())
-      return;
-
-    S.Diag(OpLoc, diag::warn_self_move) << LHSExpr->getType()
-                                        << LHSExpr->getSourceRange()
-                                        << RHSExpr->getSourceRange();
-    return;
-  }
-
-  // Member variables require a different approach to check for self moves.
-  // MemberExpr's are the same if every nested MemberExpr refers to the same
-  // Decl and that the base Expr's are DeclRefExpr's with the same Decl or
-  // the base Expr's are CXXThisExpr's.
-  const Expr *LHSBase = LHSExpr;
-  const Expr *RHSBase = RHSExpr;
-  const MemberExpr *LHSME = dyn_cast<MemberExpr>(LHSExpr);
-  const MemberExpr *RHSME = dyn_cast<MemberExpr>(RHSExpr);
-  if (!LHSME || !RHSME)
-    return;
-
-  while (LHSME && RHSME) {
-    if (LHSME->getMemberDecl()->getCanonicalDecl() !=
-        RHSME->getMemberDecl()->getCanonicalDecl())
-      return;
-
-    LHSBase = LHSME->getBase();
-    RHSBase = RHSME->getBase();
-    LHSME = dyn_cast<MemberExpr>(LHSBase);
-    RHSME = dyn_cast<MemberExpr>(RHSBase);
-  }
-
-  LHSDeclRef = dyn_cast<DeclRefExpr>(LHSBase);
-  RHSDeclRef = dyn_cast<DeclRefExpr>(RHSBase);
-  if (LHSDeclRef && RHSDeclRef) {
-    if (!LHSDeclRef->getDecl() || !RHSDeclRef->getDecl())
-      return;
-    if (LHSDeclRef->getDecl()->getCanonicalDecl() !=
-        RHSDeclRef->getDecl()->getCanonicalDecl())
-      return;
-
-    S.Diag(OpLoc, diag::warn_self_move) << LHSExpr->getType()
-                                        << LHSExpr->getSourceRange()
-                                        << RHSExpr->getSourceRange();
-    return;
-  }
-
-  if (isa<CXXThisExpr>(LHSBase) && isa<CXXThisExpr>(RHSBase))
-    S.Diag(OpLoc, diag::warn_self_move) << LHSExpr->getType()
-                                        << LHSExpr->getSourceRange()
-                                        << RHSExpr->getSourceRange();
-}
-
 /// DiagnoseSelfAssignment - Emits a warning if a value is assigned to itself.
 /// This warning is only emitted for builtin assignment operations. It is also
 /// suppressed in the event of macro expansions.
@@ -9593,7 +9509,7 @@ ExprResult Sema::CreateBuiltinBinOp(Sour
     }
     if (!ResultTy.isNull()) {
       DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
-      DiagnoseSelfMove(*this, LHS.get(), RHS.get(), OpLoc);
+      DiagnoseSelfMove(LHS.get(), RHS.get(), OpLoc);
     }
     RecordModifiableNonNullParam(*this, LHS.get());
     break;

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=225756&r1=225755&r2=225756&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Jan 12 20:32:02 2015
@@ -11199,7 +11199,12 @@ Sema::CreateOverloadedBinOp(SourceLocati
         // Cut off the implicit 'this'.
         if (isa<CXXMethodDecl>(FnDecl))
           ArgsArray = ArgsArray.slice(1);
-        checkCall(FnDecl, ArgsArray, 0, isa<CXXMethodDecl>(FnDecl), OpLoc, 
+
+        // Check for a self move.
+        if (Op == OO_Equal)
+          DiagnoseSelfMove(Args[0], Args[1], OpLoc);
+
+        checkCall(FnDecl, ArgsArray, 0, isa<CXXMethodDecl>(FnDecl), OpLoc,
                   TheCall->getSourceRange(), VariadicDoesNotApply);
 
         return MaybeBindToTemporary(TheCall);

Modified: cfe/trunk/test/SemaCXX/warn-self-move.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-self-move.cpp?rev=225756&r1=225755&r2=225756&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-self-move.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-self-move.cpp Mon Jan 12 20:32:02 2015
@@ -38,3 +38,18 @@ class field_test {
     other.x = std::move(other.x);  // expected-warning{{explicitly moving}}
   }
 };
+
+struct A {};
+struct B { A a; };
+struct C { C() {}; ~C() {} };
+void struct_test() {
+  A a;
+  a = std::move(a);  // expected-warning{{explicitly moving}}
+
+  B b;
+  b = std::move(b);  // expected-warning{{explicitly moving}}
+  b.a = std::move(b.a);  // expected-warning{{explicitly moving}}
+
+  C c;
+  c = std::move(c);  // expected-warning{{explicitly moving}}
+}





More information about the cfe-commits mailing list