1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #ifndef INCLUDED_COMPILERPLUGINS_CLANG_FUNCTIONADDRESS_HXX
11 #define INCLUDED_COMPILERPLUGINS_CLANG_FUNCTIONADDRESS_HXX
13 #include <clang/AST/RecursiveASTVisitor.h>
14 #include <unordered_set>
18 * Common code for checking if the address of a function was taken.
22 template<typename Derived
>
23 class FunctionAddress
: public RecursiveASTVisitor
<Derived
>, public loplugin::Plugin
26 explicit FunctionAddress( const InstantiationData
& data
) : loplugin::Plugin(data
) {}
28 bool TraverseCallExpr(CallExpr
* expr
) {
29 auto const saved
= callee_
;
30 callee_
= expr
->getCallee();
31 auto const ret
= RecursiveASTVisitor
<Derived
>::TraverseCallExpr(expr
);
36 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr
* expr
) {
37 auto const saved
= callee_
;
38 callee_
= expr
->getCallee();
39 auto const ret
= RecursiveASTVisitor
<Derived
>::TraverseCXXOperatorCallExpr(expr
);
44 bool TraverseCXXMemberCallExpr(CXXMemberCallExpr
* expr
) {
45 auto const saved
= callee_
;
46 callee_
= expr
->getCallee();
47 auto const ret
= RecursiveASTVisitor
<Derived
>::TraverseCXXMemberCallExpr(expr
);
52 bool TraverseCUDAKernelCallExpr(CUDAKernelCallExpr
* expr
) {
53 auto const saved
= callee_
;
54 callee_
= expr
->getCallee();
55 auto const ret
= RecursiveASTVisitor
<Derived
>::TraverseCUDAKernelCallExpr(expr
);
60 bool TraverseUserDefinedLiteral(UserDefinedLiteral
* expr
) {
61 auto const saved
= callee_
;
62 callee_
= expr
->getCallee();
63 auto const ret
= RecursiveASTVisitor
<Derived
>::TraverseUserDefinedLiteral(expr
);
68 bool VisitImplicitCastExpr(ImplicitCastExpr
const * expr
) {
69 if (expr
== callee_
) {
72 if (ignoreLocation(expr
)) {
75 if (expr
->getCastKind() != CK_FunctionToPointerDecay
) {
78 auto const dre
= dyn_cast
<DeclRefExpr
>(
79 expr
->getSubExpr()->IgnoreParens());
83 auto const fd
= dyn_cast
<FunctionDecl
>(dre
->getDecl());
87 ignoredFunctions_
.insert(fd
->getCanonicalDecl());
91 bool VisitUnaryAddrOf(UnaryOperator
const * expr
) {
92 if (ignoreLocation(expr
)) {
95 auto const dre
= dyn_cast
<DeclRefExpr
>(
96 expr
->getSubExpr()->IgnoreParenImpCasts());
100 auto const fd
= dyn_cast
<FunctionDecl
>(dre
->getDecl());
104 ignoredFunctions_
.insert(fd
->getCanonicalDecl());
109 std::unordered_set
<FunctionDecl
const *> const & getFunctionsWithAddressTaken() { return ignoredFunctions_
; }
112 std::unordered_set
<FunctionDecl
const *> ignoredFunctions_
;
113 Expr
const * callee_
= nullptr;
120 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */