summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp90
-rw-r--r--clang/lib/Sema/SemaExpr.cpp86
-rw-r--r--clang/lib/Sema/SemaOverload.cpp7
3 files changed, 97 insertions, 86 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index d14549c9e8c..9fc2bec23b1 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -8325,6 +8325,96 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *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 {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index cd953ab8986..59efbc1bb6a 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -9380,90 +9380,6 @@ static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode(
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(SourceLocation OpLoc,
}
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;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 8341c008e82..9195ee59075 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11199,7 +11199,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// 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);
OpenPOWER on IntegriCloud