summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorDavid Bolvansky <david.bolvansky@gmail.com>2019-08-18 19:14:14 +0000
committerDavid Bolvansky <david.bolvansky@gmail.com>2019-08-18 19:14:14 +0000
commit920890e26812f808a74c60ebc14cc636dac661c1 (patch)
treee4ea00cd262c5410780b19d10c72082280980507 /clang/lib/Sema/SemaExpr.cpp
parentc944438dfdbd6de9785f4652244e80d194f40b92 (diff)
downloadbcm5719-llvm-920890e26812f808a74c60ebc14cc636dac661c1.tar.gz
bcm5719-llvm-920890e26812f808a74c60ebc14cc636dac661c1.zip
[Diagnostics] Diagnose misused xor as pow
Summary: Motivation: https://twitter.com/jfbastien/status/1139298419988549632 https://twitter.com/mikemx7f/status/1139335901790625793 https://codesearch.isocpp.org/cgi-bin/cgi_ppsearch?q=10+%5E&search=Search Reviewers: jfb, rsmith, regehr, aaron.ballman Reviewed By: aaron.ballman Subscribers: lebedev.ri, Quuxplusone, erik.pilkington, riccibruno, dexonsmith, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D63423 llvm-svn: 369217
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp106
1 files changed, 105 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b218ad1f66c..e2ff34a8a79 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11011,6 +11011,107 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
return GetSignedVectorType(vType);
}
+static void diagnoseXorMisusedAsPow(Sema &S, ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc) {
+ // Do not diagnose macros.
+ if (Loc.isMacroID())
+ return;
+
+ bool Negative = false;
+ const auto *LHSInt = dyn_cast<IntegerLiteral>(LHS.get());
+ const auto *RHSInt = dyn_cast<IntegerLiteral>(RHS.get());
+
+ if (!LHSInt)
+ return;
+ if (!RHSInt) {
+ // Check negative literals.
+ if (const auto *UO = dyn_cast<UnaryOperator>(RHS.get())) {
+ if (UO->getOpcode() != UO_Minus)
+ return;
+ RHSInt = dyn_cast<IntegerLiteral>(UO->getSubExpr());
+ if (!RHSInt)
+ return;
+ Negative = true;
+ } else {
+ return;
+ }
+ }
+
+ if (LHSInt->getValue().getBitWidth() != RHSInt->getValue().getBitWidth())
+ return;
+
+ CharSourceRange ExprRange = CharSourceRange::getCharRange(
+ LHSInt->getBeginLoc(), S.getLocForEndOfToken(RHSInt->getLocation()));
+ llvm::StringRef ExprStr =
+ Lexer::getSourceText(ExprRange, S.getSourceManager(), S.getLangOpts());
+
+ CharSourceRange XorRange =
+ CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
+ llvm::StringRef XorStr =
+ Lexer::getSourceText(XorRange, S.getSourceManager(), S.getLangOpts());
+ // Do not diagnose if xor keyword/macro is used.
+ if (XorStr == "xor")
+ return;
+
+ const llvm::APInt &LeftSideValue = LHSInt->getValue();
+ const llvm::APInt &RightSideValue = RHSInt->getValue();
+ const llvm::APInt XorValue = LeftSideValue ^ RightSideValue;
+
+ std::string LHSStr = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(LHSInt->getSourceRange()),
+ S.getSourceManager(), S.getLangOpts());
+ std::string RHSStr = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(RHSInt->getSourceRange()),
+ S.getSourceManager(), S.getLangOpts());
+
+ int64_t RightSideIntValue = RightSideValue.getSExtValue();
+ if (Negative) {
+ RightSideIntValue = -RightSideIntValue;
+ RHSStr = "-" + RHSStr;
+ }
+
+ StringRef LHSStrRef = LHSStr;
+ StringRef RHSStrRef = RHSStr;
+ // Do not diagnose binary, hexadecimal, octal literals.
+ if (LHSStrRef.startswith("0b") || LHSStrRef.startswith("0B") ||
+ RHSStrRef.startswith("0b") || RHSStrRef.startswith("0B") ||
+ LHSStrRef.startswith("0x") || LHSStrRef.startswith("0X") ||
+ RHSStrRef.startswith("0x") || RHSStrRef.startswith("0X") ||
+ (LHSStrRef.size() > 1 && LHSStrRef.startswith("0")) ||
+ (RHSStrRef.size() > 1 && RHSStrRef.startswith("0")))
+ return;
+
+ if (LeftSideValue == 2 && RightSideIntValue >= 0) {
+ std::string SuggestedExpr = "1 << " + RHSStr;
+ bool Overflow = false;
+ llvm::APInt One = (LeftSideValue - 1);
+ llvm::APInt PowValue = One.sshl_ov(RightSideValue, Overflow);
+ if (Overflow) {
+ if (RightSideIntValue < 64)
+ S.Diag(Loc, diag::warn_xor_used_as_pow_base)
+ << ExprStr << XorValue.toString(10, true) << ("1LL << " + RHSStr)
+ << FixItHint::CreateReplacement(ExprRange, "1LL << " + RHSStr);
+ else
+ // TODO: 2 ^ 64 - 1
+ return;
+ } else {
+ S.Diag(Loc, diag::warn_xor_used_as_pow_base_extra)
+ << ExprStr << XorValue.toString(10, true) << SuggestedExpr
+ << PowValue.toString(10, true)
+ << FixItHint::CreateReplacement(
+ ExprRange, (RightSideIntValue == 0) ? "1" : SuggestedExpr);
+ }
+
+ S.Diag(Loc, diag::note_xor_used_as_pow_silence) << ("0x2 ^ " + RHSStr);
+ } else if (LeftSideValue == 10) {
+ std::string SuggestedValue = "1e" + std::to_string(RightSideIntValue);
+ S.Diag(Loc, diag::warn_xor_used_as_pow_base)
+ << ExprStr << XorValue.toString(10, true) << SuggestedValue
+ << FixItHint::CreateReplacement(ExprRange, SuggestedValue);
+ S.Diag(Loc, diag::note_xor_used_as_pow_silence) << ("0xA ^ " + RHSStr);
+ }
+}
+
QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc) {
// Ensure that either both operands are of the same vector type, or
@@ -11054,6 +11155,9 @@ inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
if (Opc == BO_And)
diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
+ if (Opc == BO_Xor)
+ diagnoseXorMisusedAsPow(*this, LHS, RHS, Loc);
+
ExprResult LHSResult = LHS, RHSResult = RHS;
QualType compType = UsualArithmeticConversions(LHSResult, RHSResult,
IsCompAssign);
@@ -17640,4 +17744,4 @@ ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
return new (Context)
ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);
-}
+} \ No newline at end of file
OpenPOWER on IntegriCloud