10 #include "../utils/OptionsUtils.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
15 using namespace clang::ast_matchers::internal;
24 const std::vector<std::string> NameList =
26 return hasAnyName(std::vector<StringRef>(NameList.begin(), NameList.end()));
29 SignedCharMisuseCheck::SignedCharMisuseCheck(StringRef
Name,
32 CharTypdefsToIgnoreList(Options.get(
"CharTypdefsToIgnore",
"")),
33 DiagnoseSignedUnsignedCharComparisons(
34 Options.get(
"DiagnoseSignedUnsignedCharComparisons", true)) {}
37 Options.
store(Opts,
"CharTypdefsToIgnore", CharTypdefsToIgnoreList);
38 Options.
store(Opts,
"DiagnoseSignedUnsignedCharComparisons",
39 DiagnoseSignedUnsignedCharComparisons);
43 BindableMatcher<clang::Stmt> SignedCharMisuseCheck::charCastExpression(
44 bool IsSigned,
const Matcher<clang::QualType> &IntegerType,
45 const std::string &CastBindName)
const {
49 const auto IntTypedef = qualType(
52 auto CharTypeExpr = expr();
54 CharTypeExpr = expr(hasType(
55 qualType(isAnyCharacter(), isSignedInteger(), unless(IntTypedef))));
57 CharTypeExpr = expr(hasType(qualType(
58 isAnyCharacter(), unless(isSignedInteger()), unless(IntTypedef))));
61 const auto ImplicitCastExpr =
62 implicitCastExpr(hasSourceExpression(CharTypeExpr),
63 hasImplicitDestinationType(IntegerType))
66 const auto CStyleCastExpr = cStyleCastExpr(has(ImplicitCastExpr));
67 const auto StaticCastExpr = cxxStaticCastExpr(has(ImplicitCastExpr));
68 const auto FunctionalCastExpr = cxxFunctionalCastExpr(has(ImplicitCastExpr));
73 return traverse(ast_type_traits::TK_AsIs,
74 expr(anyOf(ImplicitCastExpr, CStyleCastExpr, StaticCastExpr,
75 FunctionalCastExpr)));
79 const auto IntegerType =
80 qualType(isInteger(), unless(isAnyCharacter()), unless(booleanType()))
82 const auto SignedCharCastExpr =
83 charCastExpression(
true, IntegerType,
"signedCastExpression");
84 const auto UnSignedCharCastExpr =
85 charCastExpression(
false, IntegerType,
"unsignedCastExpression");
88 const auto AssignmentOperatorExpr =
89 expr(binaryOperator(hasOperatorName(
"="), hasLHS(hasType(IntegerType)),
90 hasRHS(SignedCharCastExpr)));
92 Finder->addMatcher(AssignmentOperatorExpr,
this);
95 const auto Declaration = varDecl(isDefinition(), hasType(IntegerType),
96 hasInitializer(SignedCharCastExpr));
98 Finder->addMatcher(Declaration,
this);
100 if (DiagnoseSignedUnsignedCharComparisons) {
102 const auto CompareOperator =
103 expr(binaryOperator(hasAnyOperatorName(
"==",
"!="),
104 anyOf(allOf(hasLHS(SignedCharCastExpr),
105 hasRHS(UnSignedCharCastExpr)),
106 allOf(hasLHS(UnSignedCharCastExpr),
107 hasRHS(SignedCharCastExpr)))))
110 Finder->addMatcher(CompareOperator,
this);
115 const auto CArraySubscript =
116 arraySubscriptExpr(hasIndex(SignedCharCastExpr)).bind(
"arraySubscript");
118 Finder->addMatcher(CArraySubscript,
this);
121 const auto STDArraySubscript =
123 hasOverloadedOperatorName(
"[]"),
124 hasArgument(0, hasType(cxxRecordDecl(hasName(
"::std::array")))),
125 hasArgument(1, SignedCharCastExpr))
126 .bind(
"arraySubscript");
128 Finder->addMatcher(STDArraySubscript,
this);
132 const auto *SignedCastExpression =
133 Result.Nodes.getNodeAs<ImplicitCastExpr>(
"signedCastExpression");
134 const auto *IntegerType = Result.Nodes.getNodeAs<QualType>(
"integerType");
135 assert(SignedCastExpression);
140 Expr::EvalResult EVResult;
141 if (!SignedCastExpression->isValueDependent() &&
142 SignedCastExpression->getSubExpr()->EvaluateAsInt(EVResult,
144 llvm::APSInt Value = EVResult.Val.getInt();
145 if (Value.isNonNegative())
149 if (
const auto *Comparison = Result.Nodes.getNodeAs<Expr>(
"comparison")) {
150 const auto *UnSignedCastExpression =
151 Result.Nodes.getNodeAs<ImplicitCastExpr>(
"unsignedCastExpression");
154 Expr::EvalResult EVResult;
155 if (!UnSignedCastExpression->isValueDependent() &&
156 UnSignedCastExpression->getSubExpr()->EvaluateAsInt(EVResult,
158 llvm::APSInt Value = EVResult.Val.getInt();
163 diag(Comparison->getBeginLoc(),
164 "comparison between 'signed char' and 'unsigned char'");
165 }
else if (Result.Nodes.getNodeAs<Expr>(
"arraySubscript")) {
166 diag(SignedCastExpression->getBeginLoc(),
167 "'signed char' to %0 conversion in array subscript; "
168 "consider casting to 'unsigned char' first.")
171 diag(SignedCastExpression->getBeginLoc(),
172 "'signed char' to %0 conversion; "
173 "consider casting to 'unsigned char' first.")