aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-01-04 06:52:15 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-01-04 06:52:15 +0000
commit9f7a6eeee441bcbb1b17208cb3abd65a0017525a (patch)
treeb5300481faa1ce3f47e23d2887b1db7f6591c85a /lib/Sema/SemaExpr.cpp
parentb2b5cc0cf908d516a107d373db963f692449a8a8 (diff)
Implement -Wself-assign, which warns on code such as:
int x = 42; x = x; // Warns here. The warning avoids macro expansions, templates, user-defined assignment operators, and volatile types, so false positives are expected to be low. The common (mis-)use of this code pattern is to silence unused variable warnings, but a more idiomatic way of doing that is '(void)x;'. A follow-up to this will add a note and fix-it hint suggesting this replacement in cases where the StmtExpr consists precisely of the self assignment. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122804 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f0e2049646..1e82432ba1 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -7460,6 +7460,40 @@ static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode(
return Opc;
}
+/// 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.
+static void DiagnoseSelfAssignment(Sema &S, Expr *lhs, Expr *rhs,
+ SourceLocation OpLoc) {
+ if (!S.ActiveTemplateInstantiations.empty())
+ return;
+ if (OpLoc.isInvalid() || OpLoc.isMacroID())
+ return;
+ lhs = lhs->IgnoreParenImpCasts();
+ rhs = rhs->IgnoreParenImpCasts();
+ const DeclRefExpr *LeftDeclRef = dyn_cast<DeclRefExpr>(lhs);
+ const DeclRefExpr *RightDeclRef = dyn_cast<DeclRefExpr>(rhs);
+ if (!LeftDeclRef || !RightDeclRef ||
+ LeftDeclRef->getLocation().isMacroID() ||
+ RightDeclRef->getLocation().isMacroID())
+ return;
+ const ValueDecl *LeftDecl =
+ cast<ValueDecl>(LeftDeclRef->getDecl()->getCanonicalDecl());
+ const ValueDecl *RightDecl =
+ cast<ValueDecl>(RightDeclRef->getDecl()->getCanonicalDecl());
+ if (LeftDecl != RightDecl)
+ return;
+ if (LeftDecl->getType().isVolatileQualified())
+ return;
+ if (const ReferenceType *RefTy = LeftDecl->getType()->getAs<ReferenceType>())
+ if (RefTy->getPointeeType().isVolatileQualified())
+ return;
+
+ S.Diag(OpLoc, diag::warn_self_assignment)
+ << LeftDeclRef->getType()
+ << lhs->getSourceRange() << rhs->getSourceRange();
+}
+
/// CreateBuiltinBinOp - Creates a new built-in binary operation with
/// operator @p Opc at location @c TokLoc. This routine only supports
/// built-in operations; ActOnBinOp handles overloaded operators.
@@ -7482,6 +7516,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
VK = lhs->getValueKind();
OK = lhs->getObjectKind();
}
+ if (!ResultTy.isNull())
+ DiagnoseSelfAssignment(*this, lhs, rhs, OpLoc);
break;
case BO_PtrMemD:
case BO_PtrMemI: