11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 using namespace clang::ast_matchers;
18 namespace cppcoreguidelines {
20 const internal::VariadicDynCastAllOfMatcher<Stmt, VAArgExpr>
vAArgExpr;
22 void ProTypeVarargCheck::registerMatchers(MatchFinder *
Finder) {
23 if (!getLangOpts().CPlusPlus)
26 Finder->addMatcher(
vAArgExpr().bind(
"va_use"),
this);
29 callExpr(callee(functionDecl(isVariadic())))
35 const auto *FDecl = dyn_cast<FunctionDecl>(C->getCalleeDecl());
39 auto N = FDecl->getNumParams();
40 if (C->getNumArgs() != N + 1)
44 dyn_cast<IntegerLiteral>(C->getArg(N)->IgnoreParenImpCasts());
48 if (IntLit->getValue() != I)
54 void ProTypeVarargCheck::check(
const MatchFinder::MatchResult &
Result) {
55 if (
const auto *Matched = Result.Nodes.getNodeAs<CallExpr>(
"callvararg")) {
58 diag(Matched->getExprLoc(),
"do not call c-style vararg functions");
61 if (
const auto *Matched = Result.Nodes.getNodeAs<Expr>(
"va_use")) {
62 diag(Matched->getExprLoc(),
63 "do not use va_start/va_arg to define c-style vararg functions; "
64 "use variadic templates instead");
67 if (
const auto *Matched = Result.Nodes.getNodeAs<VarDecl>(
"va_list")) {
68 auto SR = Matched->getSourceRange();
71 diag(SR.getBegin(),
"do not declare variables of type va_list; "
72 "use variadic templates instead");
std::unique_ptr< ast_matchers::MatchFinder > Finder
const internal::VariadicDynCastAllOfMatcher< Stmt, VAArgExpr > vAArgExpr
static bool hasSingleVariadicArgumentWithValue(const CallExpr *C, uint64_t I)