10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/ASTMatchers/ASTMatchers.h"
18 namespace cppcoreguidelines {
20 const internal::VariadicDynCastAllOfMatcher<Stmt, VAArgExpr>
vAArgExpr;
24 "__builtin_isgreater",
25 "__builtin_isgreaterequal",
27 "__builtin_islessequal",
28 "__builtin_islessgreater",
29 "__builtin_isunordered",
30 "__builtin_fpclassify",
33 "__builtin_isinf_sign",
37 "__builtin_constant_p",
38 "__builtin_classify_type",
40 "__builtin_assume_aligned",
44 "__builtin_shufflevector",
46 "__builtin_convertvector",
47 "__builtin_call_with_static_chain",
48 "__builtin_annotation",
49 "__builtin_add_overflow",
50 "__builtin_sub_overflow",
51 "__builtin_mul_overflow",
52 "__builtin_preserve_access_index",
53 "__builtin_nontemporal_store",
54 "__builtin_nontemporal_load",
55 "__builtin_ms_va_start",
61 ASTContext &Context = Finder->getASTContext();
62 QualType Desugar = Node.getDesugaredType(Context);
63 return Context.getBuiltinVaListType().getDesugaredType(Context) == Desugar ||
64 Context.getBuiltinMSVaListType().getDesugaredType(Context) == Desugar;
68 ast_matchers::internal::Matcher<QualType>, InnerType) {
69 return InnerType.matches(Node.getOriginalType(), Finder,
Builder);
73 void ProTypeVarargCheck::registerMatchers(MatchFinder *Finder) {
74 Finder->addMatcher(
vAArgExpr().bind(
"va_use"),
this);
77 callExpr(callee(functionDecl(isVariadic(),
83 varDecl(unless(parmVarDecl()),
85 anyOf(isVAList(), decayedType(hasOriginalType(isVAList()))))))
91 const auto *FDecl = dyn_cast<FunctionDecl>(C->getCalleeDecl());
95 auto N = FDecl->getNumParams();
96 if (C->getNumArgs() != N + 1)
100 dyn_cast<IntegerLiteral>(C->getArg(N)->IgnoreParenImpCasts());
104 if (IntLit->getValue() != I)
110 void ProTypeVarargCheck::check(
const MatchFinder::MatchResult &Result) {
111 if (
const auto *Matched = Result.Nodes.getNodeAs<CallExpr>(
"callvararg")) {
114 diag(Matched->getExprLoc(),
"do not call c-style vararg functions");
117 if (
const auto *Matched = Result.Nodes.getNodeAs<Expr>(
"va_use")) {
118 diag(Matched->getExprLoc(),
119 "do not use va_arg to define c-style vararg functions; "
120 "use variadic templates instead");
123 if (
const auto *Matched = Result.Nodes.getNodeAs<VarDecl>(
"va_list")) {
124 auto SR = Matched->getSourceRange();
127 diag(SR.getBegin(),
"do not declare variables of type va_list; "
128 "use variadic templates instead");