11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 #include "clang/Tooling/FixIt.h" 23 return Node.getValue().getZExtValue() > N;
27 StringConstructorCheck::StringConstructorCheck(StringRef
Name,
30 WarnOnLargeLength(Options.get(
"WarnOnLargeLength", 1) != 0),
31 LargeLengthThreshold(Options.get(
"LargeLengthThreshold", 0x800000)) {}
34 Options.
store(Opts,
"WarnOnLargeLength", WarnOnLargeLength);
35 Options.
store(Opts,
"LargeLengthThreshold", LargeLengthThreshold);
42 const auto ZeroExpr = expr(ignoringParenImpCasts(integerLiteral(equals(0))));
43 const auto CharExpr = expr(ignoringParenImpCasts(characterLiteral()));
44 const auto NegativeExpr = expr(ignoringParenImpCasts(
45 unaryOperator(hasOperatorName(
"-"),
46 hasUnaryOperand(integerLiteral(unless(equals(0)))))));
47 const auto LargeLengthExpr = expr(ignoringParenImpCasts(
48 integerLiteral(isBiggerThan(LargeLengthThreshold))));
49 const auto CharPtrType = type(anyOf(pointerType(), arrayType()));
52 const auto BoundStringLiteral = stringLiteral().bind(
"str");
53 const auto ConstStrLiteralDecl = varDecl(
54 isDefinition(), hasType(constantArrayType()), hasType(isConstQualified()),
55 hasInitializer(ignoringParenImpCasts(BoundStringLiteral)));
56 const auto ConstPtrStrLiteralDecl = varDecl(
58 hasType(pointerType(pointee(isAnyCharacter(), isConstQualified()))),
59 hasInitializer(ignoringParenImpCasts(BoundStringLiteral)));
60 const auto ConstStrLiteral = expr(ignoringParenImpCasts(anyOf(
61 BoundStringLiteral, declRefExpr(hasDeclaration(anyOf(
62 ConstPtrStrLiteralDecl, ConstStrLiteralDecl))))));
68 hasDeclaration(cxxMethodDecl(hasName(
"basic_string"))),
69 hasArgument(0, hasType(qualType(isInteger()))),
70 hasArgument(1, hasType(qualType(isInteger()))),
73 hasArgument(0, CharExpr.bind(
"swapped-parameter")),
75 hasArgument(0, ZeroExpr.bind(
"empty-string")),
77 hasArgument(0, NegativeExpr.bind(
"negative-length")),
79 hasArgument(0, LargeLengthExpr.bind(
"large-length"))))
87 hasDeclaration(cxxMethodDecl(hasName(
"basic_string"))),
88 hasArgument(0, hasType(CharPtrType)),
89 hasArgument(1, hasType(isInteger())),
92 hasArgument(1, ZeroExpr.bind(
"empty-string")),
94 hasArgument(1, NegativeExpr.bind(
"negative-length")),
96 hasArgument(1, LargeLengthExpr.bind(
"large-length")),
98 allOf(hasArgument(0, ConstStrLiteral.bind(
"literal-with-length")),
99 hasArgument(1, ignoringParenImpCasts(
100 integerLiteral().bind(
"int"))))))
101 .bind(
"constructor"),
106 const ASTContext &
Ctx = *Result.Context;
107 const auto *E = Result.Nodes.getNodeAs<CXXConstructExpr>(
"constructor");
108 assert(E &&
"missing constructor expression");
109 SourceLocation
Loc = E->getLocStart();
111 if (Result.Nodes.getNodeAs<Expr>(
"swapped-parameter")) {
112 const Expr *P0 = E->getArg(0);
113 const Expr *P1 = E->getArg(1);
114 diag(Loc,
"string constructor parameters are probably swapped;" 115 " expecting string(count, character)")
116 << tooling::fixit::createReplacement(*P0, *P1, Ctx)
117 << tooling::fixit::createReplacement(*P1, *P0, Ctx);
118 }
else if (Result.Nodes.getNodeAs<Expr>(
"empty-string")) {
119 diag(Loc,
"constructor creating an empty string");
120 }
else if (Result.Nodes.getNodeAs<Expr>(
"negative-length")) {
121 diag(Loc,
"negative value used as length parameter");
122 }
else if (Result.Nodes.getNodeAs<Expr>(
"large-length")) {
123 if (WarnOnLargeLength)
124 diag(Loc,
"suspicious large length parameter");
125 }
else if (Result.Nodes.getNodeAs<Expr>(
"literal-with-length")) {
126 const auto *Str = Result.Nodes.getNodeAs<StringLiteral>(
"str");
127 const auto *Lit = Result.Nodes.getNodeAs<IntegerLiteral>(
"int");
128 if (Lit->getValue().ugt(Str->getLength())) {
129 diag(Loc,
"length is bigger then string literal size");
SourceLocation Loc
'#' location in the include directive
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
LangOptions getLangOpts() const
Returns the language options from the context.
Base class for all clang-tidy checks.
std::map< std::string, std::string > OptionMap
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
AST_MATCHER_P(FunctionDecl, throws, internal::Matcher< Type >, InnerMatcher)
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
tooling::ExecutionContext * Ctx
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.