Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / compilerplugins / clang / functionaddress.hxx
blobdc34262a50b0deaabf99a041eddd548342e3baac
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #ifndef INCLUDED_COMPILERPLUGINS_CLANG_FUNCTIONADDRESS_HXX
11 #define INCLUDED_COMPILERPLUGINS_CLANG_FUNCTIONADDRESS_HXX
13 #include <clang/AST/RecursiveASTVisitor.h>
14 #include <unordered_set>
15 #include "plugin.hxx"
17 /**
18 * Common code for checking if the address of a function was taken.
20 namespace loplugin {
22 template<typename Derived>
23 class FunctionAddress : public RecursiveASTVisitor<Derived>, public loplugin::Plugin
25 public:
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);
32 callee_ = saved;
33 return ret;
36 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * expr) {
37 auto const saved = callee_;
38 callee_ = expr->getCallee();
39 auto const ret = RecursiveASTVisitor<Derived>::TraverseCXXOperatorCallExpr(expr);
40 callee_ = saved;
41 return ret;
44 bool TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr) {
45 auto const saved = callee_;
46 callee_ = expr->getCallee();
47 auto const ret = RecursiveASTVisitor<Derived>::TraverseCXXMemberCallExpr(expr);
48 callee_ = saved;
49 return ret;
52 bool TraverseCUDAKernelCallExpr(CUDAKernelCallExpr * expr) {
53 auto const saved = callee_;
54 callee_ = expr->getCallee();
55 auto const ret = RecursiveASTVisitor<Derived>::TraverseCUDAKernelCallExpr(expr);
56 callee_ = saved;
57 return ret;
60 bool TraverseUserDefinedLiteral(UserDefinedLiteral * expr) {
61 auto const saved = callee_;
62 callee_ = expr->getCallee();
63 auto const ret = RecursiveASTVisitor<Derived>::TraverseUserDefinedLiteral(expr);
64 callee_ = saved;
65 return ret;
68 bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) {
69 if (expr == callee_) {
70 return true;
72 if (ignoreLocation(expr)) {
73 return true;
75 if (expr->getCastKind() != CK_FunctionToPointerDecay) {
76 return true;
78 auto const dre = dyn_cast<DeclRefExpr>(
79 expr->getSubExpr()->IgnoreParens());
80 if (dre == nullptr) {
81 return true;
83 auto const fd = dyn_cast<FunctionDecl>(dre->getDecl());
84 if (fd == nullptr) {
85 return true;
87 ignoredFunctions_.insert(fd->getCanonicalDecl());
88 return true;
91 bool VisitUnaryAddrOf(UnaryOperator const * expr) {
92 if (ignoreLocation(expr)) {
93 return true;
95 auto const dre = dyn_cast<DeclRefExpr>(
96 expr->getSubExpr()->IgnoreParenImpCasts());
97 if (dre == nullptr) {
98 return true;
100 auto const fd = dyn_cast<FunctionDecl>(dre->getDecl());
101 if (fd == nullptr) {
102 return true;
104 ignoredFunctions_.insert(fd->getCanonicalDecl());
105 return true;
108 protected:
109 std::unordered_set<FunctionDecl const *> const & getFunctionsWithAddressTaken() { return ignoredFunctions_; }
111 private:
112 std::unordered_set<FunctionDecl const *> ignoredFunctions_;
113 Expr const * callee_ = nullptr;
118 #endif
120 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */