clang-tools 3.8.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

ProTypeVarargCheck.cpp
Go to the documentation of this file.
1 //===--- ProTypeVarargCheck.cpp - clang-tidy-------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "ProTypeVarargCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13
14 using namespace clang::ast_matchers;
15
16 namespace clang {
17 namespace tidy {
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())))
29 .bind("callvararg"),
30 this);
31 }
32
33 static bool hasSingleVariadicArgumentWithValue(const CallExpr *C, uint64_t I) {
34 const auto *FDecl = dyn_cast<FunctionDecl>(C->getCalleeDecl());
35 if (!FDecl)
36 return false;
37
38 auto N = FDecl->getNumParams(); // Number of parameters without '...'
39 if (C->getNumArgs() != N + 1)
40 return false; // more/less than one argument passed to '...'
41
42 const auto *IntLit =
43 dyn_cast<IntegerLiteral>(C->getArg(N)->IgnoreParenImpCasts());
44 if (!IntLit)
45 return false;
46
47 if (IntLit->getValue() != I)
48 return false;
49
50 return true;
51 }
52
53 void ProTypeVarargCheck::check(const MatchFinder::MatchResult &Result) {
54 if (const auto *Matched = Result.Nodes.getNodeAs<CallExpr>("callvararg")) {
55 if (hasSingleVariadicArgumentWithValue(Matched, 0))
56 return;
57 diag(Matched->getExprLoc(), "do not call c-style vararg functions");
58 }
59
60 if (const auto *Matched = Result.Nodes.getNodeAs<Expr>("va_use")) {
61 diag(Matched->getExprLoc(),
62 "do not use va_start/va_arg to define c-style vararg functions; "
63 "use variadic templates instead");
64 }
65
66 if (const auto *Matched = Result.Nodes.getNodeAs<VarDecl>("va_list")) {
67 auto SR = Matched->getSourceRange();
68 if (SR.isInvalid())
69 return; // some implicitly generated builtins take va_list
70 diag(SR.getBegin(), "do not declare variables of type va_list; "
71 "use variadic templates instead");
72 }
73 }
74
75 } // namespace tidy
76 } // namespace clang
clang::tidy::vAArgExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, VAArgExpr > vAArgExpr
Definition: ProTypeVarargCheck.cpp:19
Finder
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:188
ProTypeVarargCheck.h
clang::tidy::hasSingleVariadicArgumentWithValue
static bool hasSingleVariadicArgumentWithValue(const CallExpr *C, uint64_t I)
Definition: ProTypeVarargCheck.cpp:33
Result
const NamedDecl * Result
Definition: USRFinder.cpp:121