10#include "../utils/TransformerClangTidyCheck.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/AST/Decl.h"
13#include "clang/AST/OperationKinds.h"
14#include "clang/ASTMatchers/ASTMatchFinder.h"
15#include "clang/ASTMatchers/ASTMatchers.h"
16#include "clang/Tooling/Transformer/RangeSelector.h"
17#include "clang/Tooling/Transformer/RewriteRule.h"
18#include "clang/Tooling/Transformer/Stencil.h"
19#include "llvm/ADT/StringRef.h"
24using namespace ::clang::transformer;
29 return Node.getNumInits() == N;
32AST_MATCHER(clang::VarDecl, isDirectInitialization) {
33 return Node.getInitStyle() != clang::VarDecl::InitializationStyle::CInit;
39 auto construction_warning =
40 cat(
"constructing basic_string_view from null is undefined; replace with "
41 "the default constructor");
42 auto static_cast_warning =
43 cat(
"casting to basic_string_view from null is undefined; replace with "
45 auto argument_construction_warning =
46 cat(
"passing null as basic_string_view is undefined; replace with the "
48 auto assignment_warning =
49 cat(
"assignment to basic_string_view from null is undefined; replace "
50 "with the default constructor");
51 auto relative_comparison_warning =
52 cat(
"comparing basic_string_view to null is undefined; replace with the "
54 auto equality_comparison_warning =
55 cat(
"comparing basic_string_view to null is undefined; replace with the "
59 auto HasBasicStringViewType = hasType(hasUnqualifiedDesugaredType(recordType(
60 hasDeclaration(cxxRecordDecl(hasName(
"::std::basic_string_view"))))));
63 auto NullLiteral = implicitCastExpr(
64 hasCastKind(clang::CK_NullToPointer),
65 hasSourceExpression(ignoringParens(cxxNullPtrLiteralExpr())));
68 auto NullInitList = initListExpr(initCountIs(1), hasInit(0, NullLiteral));
71 auto EmptyInitList = initListExpr(initCountIs(0));
74 auto BasicStringViewConstructingFromNullExpr =
76 HasBasicStringViewType, argumentCountIs(1),
77 hasAnyArgument( anyOf(
78 NullLiteral, NullInitList, EmptyInitList)),
79 unless(cxxTemporaryObjectExpr()),
80 has(expr().bind(
"null_arg_expr")))
81 .bind(
"construct_expr");
84 auto HandleTemporaryCXXFunctionalCastExpr =
85 makeRule(cxxFunctionalCastExpr(hasSourceExpression(
86 BasicStringViewConstructingFromNullExpr)),
87 remove(node(
"null_arg_expr")), construction_warning);
90 auto HandleTemporaryCXXTemporaryObjectExprAndCompoundLiteralExpr = makeRule(
91 cxxTemporaryObjectExpr(cxxConstructExpr(
92 HasBasicStringViewType, argumentCountIs(1),
93 hasAnyArgument( anyOf(
94 NullLiteral, NullInitList, EmptyInitList)),
95 has(expr().bind(
"null_arg_expr")))),
96 remove(node(
"null_arg_expr")), construction_warning);
99 auto HandleTemporaryCStyleCastExpr = makeRule(
101 hasSourceExpression(BasicStringViewConstructingFromNullExpr)),
102 changeTo(node(
"null_arg_expr"), cat(
"{}")), construction_warning);
105 auto HandleTemporaryCXXStaticCastExpr = makeRule(
107 hasSourceExpression(BasicStringViewConstructingFromNullExpr)),
108 changeTo(node(
"null_arg_expr"), cat(
"\"\"")), static_cast_warning);
111 auto HandleStackCopyInitialization = makeRule(
112 varDecl(HasBasicStringViewType,
113 hasInitializer(ignoringImpCasts(
114 cxxConstructExpr(BasicStringViewConstructingFromNullExpr,
115 unless(isListInitialization())))),
116 unless(isDirectInitialization())),
117 changeTo(node(
"null_arg_expr"), cat(
"{}")), construction_warning);
120 auto HandleStackCopyListInitialization =
121 makeRule(varDecl(HasBasicStringViewType,
122 hasInitializer(cxxConstructExpr(
123 BasicStringViewConstructingFromNullExpr,
124 isListInitialization())),
125 unless(isDirectInitialization())),
126 remove(node(
"null_arg_expr")), construction_warning);
129 auto HandleStackDirectInitialization =
130 makeRule(varDecl(HasBasicStringViewType,
131 hasInitializer(cxxConstructExpr(
132 BasicStringViewConstructingFromNullExpr,
133 unless(isListInitialization()))),
134 isDirectInitialization())
136 changeTo(node(
"construct_expr"), cat(name(
"var_decl"))),
137 construction_warning);
140 auto HandleStackDirectListInitialization =
141 makeRule(varDecl(HasBasicStringViewType,
142 hasInitializer(cxxConstructExpr(
143 BasicStringViewConstructingFromNullExpr,
144 isListInitialization())),
145 isDirectInitialization()),
146 remove(node(
"null_arg_expr")), construction_warning);
149 auto HandleFieldInClassCopyInitialization = makeRule(
150 fieldDecl(HasBasicStringViewType,
151 hasInClassInitializer(ignoringImpCasts(
152 cxxConstructExpr(BasicStringViewConstructingFromNullExpr,
153 unless(isListInitialization()))))),
154 changeTo(node(
"null_arg_expr"), cat(
"{}")), construction_warning);
158 auto HandleFieldInClassCopyListAndDirectListInitialization = makeRule(
159 fieldDecl(HasBasicStringViewType,
160 hasInClassInitializer(ignoringImpCasts(
161 cxxConstructExpr(BasicStringViewConstructingFromNullExpr,
162 isListInitialization())))),
163 remove(node(
"null_arg_expr")), construction_warning);
166 auto HandleConstructorDirectInitialization =
167 makeRule(cxxCtorInitializer(forField(fieldDecl(HasBasicStringViewType)),
168 withInitializer(cxxConstructExpr(
169 BasicStringViewConstructingFromNullExpr,
170 unless(isListInitialization())))),
171 remove(node(
"null_arg_expr")), construction_warning);
174 auto HandleConstructorDirectListInitialization =
175 makeRule(cxxCtorInitializer(forField(fieldDecl(HasBasicStringViewType)),
176 withInitializer(cxxConstructExpr(
177 BasicStringViewConstructingFromNullExpr,
178 isListInitialization()))),
179 remove(node(
"null_arg_expr")), construction_warning);
182 auto HandleDefaultArgumentCopyInitialization = makeRule(
183 parmVarDecl(HasBasicStringViewType,
184 hasInitializer(ignoringImpCasts(
185 cxxConstructExpr(BasicStringViewConstructingFromNullExpr,
186 unless(isListInitialization()))))),
187 changeTo(node(
"null_arg_expr"), cat(
"{}")), construction_warning);
190 auto HandleDefaultArgumentCopyListInitialization =
191 makeRule(parmVarDecl(HasBasicStringViewType,
192 hasInitializer(cxxConstructExpr(
193 BasicStringViewConstructingFromNullExpr,
194 isListInitialization()))),
195 remove(node(
"null_arg_expr")), construction_warning);
198 auto HandleHeapDirectInitialization = makeRule(
199 cxxNewExpr(has(cxxConstructExpr(BasicStringViewConstructingFromNullExpr,
200 unless(isListInitialization()))),
201 unless(isArray()), unless(hasAnyPlacementArg(anything()))),
202 remove(node(
"null_arg_expr")), construction_warning);
205 auto HandleHeapDirectListInitialization = makeRule(
206 cxxNewExpr(has(cxxConstructExpr(BasicStringViewConstructingFromNullExpr,
207 isListInitialization())),
208 unless(isArray()), unless(hasAnyPlacementArg(anything()))),
209 remove(node(
"null_arg_expr")), construction_warning);
212 auto HandleFunctionArgumentInitialization =
213 makeRule(callExpr(hasAnyArgument(ignoringImpCasts(
214 BasicStringViewConstructingFromNullExpr)),
215 unless(cxxOperatorCallExpr())),
216 changeTo(node(
"construct_expr"), cat(
"\"\"")),
217 argument_construction_warning);
220 auto HandleAssignment = makeRule(
221 cxxOperatorCallExpr(hasOverloadedOperatorName(
"="),
222 hasRHS(materializeTemporaryExpr(
223 has(BasicStringViewConstructingFromNullExpr)))),
224 changeTo(node(
"construct_expr"), cat(
"{}")), assignment_warning);
227 auto HandleRelativeComparison = makeRule(
228 cxxOperatorCallExpr(hasAnyOverloadedOperatorName(
"<",
"<=",
">",
">="),
229 hasEitherOperand(ignoringImpCasts(
230 BasicStringViewConstructingFromNullExpr))),
231 changeTo(node(
"construct_expr"), cat(
"\"\"")),
232 relative_comparison_warning);
235 auto HandleEmptyEqualityComparison = makeRule(
237 hasOverloadedOperatorName(
"=="),
238 hasOperands(ignoringImpCasts(BasicStringViewConstructingFromNullExpr),
239 traverse(clang::TK_IgnoreUnlessSpelledInSource,
240 expr().bind(
"instance"))))
242 changeTo(node(
"root"), cat(access(
"instance", cat(
"empty")),
"()")),
243 equality_comparison_warning);
246 auto HandleNonEmptyEqualityComparison = makeRule(
248 hasOverloadedOperatorName(
"!="),
249 hasOperands(ignoringImpCasts(BasicStringViewConstructingFromNullExpr),
250 traverse(clang::TK_IgnoreUnlessSpelledInSource,
251 expr().bind(
"instance"))))
253 changeTo(node(
"root"), cat(
"!", access(
"instance", cat(
"empty")),
"()")),
254 equality_comparison_warning);
257 auto HandleReturnStatement = makeRule(
258 returnStmt(hasReturnValue(
259 ignoringImpCasts(BasicStringViewConstructingFromNullExpr))),
260 changeTo(node(
"construct_expr"), cat(
"{}")), construction_warning);
263 auto HandleConstructorInvocation =
264 makeRule(cxxConstructExpr(
267 BasicStringViewConstructingFromNullExpr)),
268 unless(HasBasicStringViewType)),
269 changeTo(node(
"construct_expr"), cat(
"\"\"")),
270 argument_construction_warning);
273 {HandleTemporaryCXXFunctionalCastExpr,
274 HandleTemporaryCXXTemporaryObjectExprAndCompoundLiteralExpr,
275 HandleTemporaryCStyleCastExpr,
276 HandleTemporaryCXXStaticCastExpr,
277 HandleStackCopyInitialization,
278 HandleStackCopyListInitialization,
279 HandleStackDirectInitialization,
280 HandleStackDirectListInitialization,
281 HandleFieldInClassCopyInitialization,
282 HandleFieldInClassCopyListAndDirectListInitialization,
283 HandleConstructorDirectInitialization,
284 HandleConstructorDirectListInitialization,
285 HandleDefaultArgumentCopyInitialization,
286 HandleDefaultArgumentCopyListInitialization,
287 HandleHeapDirectInitialization,
288 HandleHeapDirectListInitialization,
289 HandleFunctionArgumentInitialization,
291 HandleRelativeComparison,
292 HandleEmptyEqualityComparison,
293 HandleNonEmptyEqualityComparison,
294 HandleReturnStatement,
295 HandleConstructorInvocation});
llvm::SmallString< 256U > Name
::clang::DynTypedNode Node
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
StringviewNullptrCheck(StringRef Name, ClangTidyContext *Context)
AST_MATCHER_P(FunctionDecl, parameterCountGE, unsigned, N)
Matches functions that have at least the specified amount of parameters.
RewriteRuleWith< std::string > StringviewNullptrCheckImpl()
AST_MATCHER(clang::VarDecl, hasConstantDeclaration)