clang-tools 10.0.0

ProTypeVarargCheck.cpp
Go to the documentation of this file.
1 //===--- ProTypeVarargCheck.cpp - clang-tidy-------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "ProTypeVarargCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12
13 using namespace clang::ast_matchers;
14
15 namespace clang {
16 namespace tidy {
17 namespace cppcoreguidelines {
18
19 const internal::VariadicDynCastAllOfMatcher<Stmt, VAArgExpr> vAArgExpr;
20
21 void ProTypeVarargCheck::registerMatchers(MatchFinder *Finder) {
22 if (!getLangOpts().CPlusPlus)
23 return;
24
25 Finder->addMatcher(vAArgExpr().bind("va_use"), this);
26
27 Finder->addMatcher(
28 callExpr(callee(functionDecl(isVariadic()))).bind("callvararg"), this);
29 }
30
31 static bool hasSingleVariadicArgumentWithValue(const CallExpr *C, uint64_t I) {
32 const auto *FDecl = dyn_cast<FunctionDecl>(C->getCalleeDecl());
33 if (!FDecl)
34 return false;
35
36 auto N = FDecl->getNumParams(); // Number of parameters without '...'
37 if (C->getNumArgs() != N + 1)
38 return false; // more/less than one argument passed to '...'
39
40 const auto *IntLit =
41 dyn_cast<IntegerLiteral>(C->getArg(N)->IgnoreParenImpCasts());
42 if (!IntLit)
43 return false;
44
45 if (IntLit->getValue() != I)
46 return false;
47
48 return true;
49 }
50
51 void ProTypeVarargCheck::check(const MatchFinder::MatchResult &Result) {
52 if (const auto *Matched = Result.Nodes.getNodeAs<CallExpr>("callvararg")) {
53 if (hasSingleVariadicArgumentWithValue(Matched, 0))
54 return;
55 diag(Matched->getExprLoc(), "do not call c-style vararg functions");
56 }
57
58 if (const auto *Matched = Result.Nodes.getNodeAs<Expr>("va_use")) {
59 diag(Matched->getExprLoc(),
60 "do not use va_start/va_arg to define c-style vararg functions; "
61 "use variadic templates instead");
62 }
63
64 if (const auto *Matched = Result.Nodes.getNodeAs<VarDecl>("va_list")) {
65 auto SR = Matched->getSourceRange();
66 if (SR.isInvalid())
67 return; // some implicitly generated builtins take va_list
68 diag(SR.getBegin(), "do not declare variables of type va_list; "
69 "use variadic templates instead");
70 }
71 }
72
73 } // namespace cppcoreguidelines
74 } // namespace tidy
75 } // namespace clang
clang::ast_matchers
Definition: AbseilMatcher.h:14
clang::tidy::cppcoreguidelines::vAArgExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, VAArgExpr > vAArgExpr
Definition: ProTypeVarargCheck.cpp:19
ProTypeVarargCheck.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::cppcoreguidelines::hasSingleVariadicArgumentWithValue
static bool hasSingleVariadicArgumentWithValue(const CallExpr *C, uint64_t I)
Definition: ProTypeVarargCheck.cpp:31