xbolva00 updated this revision to Diff 205058.
xbolva00 added a comment.
More tests
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D63423/new/
https://reviews.llvm.org/D63423
Files:
include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/SemaCXX/warn-xor-as-pow.cpp
Index: test/SemaCXX/warn-xor-as-pow.cpp
===================================================================
--- test/SemaCXX/warn-xor-as-pow.cpp
+++ test/SemaCXX/warn-xor-as-pow.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wxor-as-pow %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+#define TWO 2
+#define TEN 10
+#define TWO_ULL 2ULL
+void test(unsigned a, unsigned b) {
+ unsigned res;
+ res = a ^ 5;
+ res = 2 ^ b;
+ res = a ^ b;
+ res = 2 ^ 0;
+ res = 2 ^ 1; // expected-warning {{result of '2 ^ 1' is 3, maybe you mean '1<<1' (2)?}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"1<<1"
+ res = 2 ^ 8; // expected-warning {{result of '2 ^ 8' is 10, maybe you mean '1<<8' (256)?}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"1<<8"
+ res = TWO ^ 8; // expected-warning {{result of 'TWO ^ 8' is 10, maybe you mean '1<<8' (256)?}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:18}:"1<<8"
+ res = 2 ^ 16; // expected-warning {{result of '2 ^ 16' is 18, maybe you mean '1<<16' (65536)?}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:17}:"1<<16"
+ res = 0b10 ^ 16;
+ res = 2 ^ 0b100;
+ res = 2 xor 16;
+ unsigned char two = 2;
+ res = two ^ 16;
+ res = TWO_ULL ^ 16;
+
+ res = 10 ^ 0;
+ res = 10 ^ 1; // expected-warning {{result of '10 ^ 1' is 11, maybe you mean '10'?}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:17}:"10"
+ res = 10 ^ 10; // expected-warning {{result of '10 ^ 10' is 0, maybe you mean '10000000000'?}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:18}:"10000000000"
+ res = TEN ^ 10; // expected-warning {{result of 'TEN ^ 10' is 0, maybe you mean '10000000000'?}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:19}:"10000000000"
+ res = 10 xor 10;
+}
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -10890,6 +10890,50 @@
return GetSignedVectorType(vType);
}
+static void diagnoseXorMisusedAsPow(Sema &S, ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc) {
+ auto *LHSInt = dyn_cast<IntegerLiteral>(LHS.get());
+ auto *RHSInt = dyn_cast<IntegerLiteral>(RHS.get());
+ if (!LHSInt || !RHSInt)
+ return;
+
+ if (LHSInt->getValue().getBitWidth() != RHSInt->getValue().getBitWidth())
+ return;
+
+ CharSourceRange OpRange = CharSourceRange::getCharRange(
+ LHSInt->getBeginLoc(), S.getLocForEndOfToken(RHSInt->getLocation()));
+ llvm::StringRef ExprStr =
+ Lexer::getSourceText(OpRange, S.getSourceManager(), S.getLangOpts());
+
+ if (S.getLangOpts().CPlusPlus) {
+ // Do not diagnose binary literals
+ if (ExprStr.find("0b") != llvm::StringRef::npos)
+ return;
+ // Do not diagnose if xor keyword is used
+ if (ExprStr.find("xor") != llvm::StringRef::npos)
+ return;
+ }
+
+ int64_t RightSideValue = RHSInt->getValue().getSExtValue();
+ if (RightSideValue < 1)
+ return;
+
+ llvm::APInt XorValue = LHSInt->getValue() ^ RHSInt->getValue();
+ if (LHSInt->getValue() == 2) {
+ llvm::APInt PowValue = (LHSInt->getValue() - 1) << RHSInt->getValue();
+ std::string SuggestedExpr = "1<<" + RHSInt->getValue().toString(10, true);
+ S.Diag(Loc, diag::warn_xor_used_as_pow_base_two)
+ << ExprStr << XorValue.toString(10, true) << SuggestedExpr
+ << PowValue.toString(10, true)
+ << FixItHint::CreateReplacement(OpRange, SuggestedExpr);
+ } else if (LHSInt->getValue() == 10) {
+ std::string SuggestedValue = "1" + std::string(RightSideValue, '0');
+ S.Diag(Loc, diag::warn_xor_used_as_pow_base_ten)
+ << ExprStr << XorValue.toString(10, true) << SuggestedValue
+ << FixItHint::CreateReplacement(OpRange, SuggestedValue);
+ }
+}
+
QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc) {
// Ensure that either both operands are of the same vector type, or
@@ -10933,6 +10977,9 @@
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);
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -3302,6 +3302,14 @@
"code; pointer may be assumed to always convert to true">,
InGroup<UndefinedBoolConversion>;
+def warn_xor_used_as_pow_base_two : Warning<
+ "result of '%0' is %1, maybe you mean '%2' (%3)?">,
+ InGroup<XorAsPow>;
+
+def warn_xor_used_as_pow_base_ten : Warning<
+ "result of '%0' is %1, maybe you mean '%2'?">,
+ InGroup<XorAsPow>;
+
def warn_null_pointer_compare : Warning<
"comparison of %select{address of|function|array}0 '%1' %select{not |}2"
"equal to a null pointer is always %select{true|false}2">,
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -505,6 +505,7 @@
def GNUUnionCast : DiagGroup<"gnu-union-cast">;
def GNUVariableSizedTypeNotAtEnd : DiagGroup<"gnu-variable-sized-type-not-at-end">;
def Varargs : DiagGroup<"varargs">;
+def XorAsPow : DiagGroup<"xor-as-pow">;
def Unsequenced : DiagGroup<"unsequenced">;
// GCC name for -Wunsequenced
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits