diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2011-01-04 06:52:15 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2011-01-04 06:52:15 +0000 |
commit | 9f7a6eeee441bcbb1b17208cb3abd65a0017525a (patch) | |
tree | b5300481faa1ce3f47e23d2887b1db7f6591c85a /lib/Sema/SemaExpr.cpp | |
parent | b2b5cc0cf908d516a107d373db963f692449a8a8 (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.cpp | 36 |
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: |