Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / compilerplugins / clang / functionaddress.hxx
blobd2bf19e14f659a588431f5f696297ebdab717433
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 #pragma once
12 #include <clang/AST/RecursiveASTVisitor.h>
13 #include <unordered_set>
14 #include "plugin.hxx"
16 /**
17 * Common code for checking if the address of a function was taken.
19 namespace loplugin {
21 template<typename Base>
22 class FunctionAddress : public Base
24 public:
25 explicit FunctionAddress( const InstantiationData& data ) : Base(data) {}
27 bool TraverseCallExpr(CallExpr * expr) {
28 auto const saved = callee_;
29 callee_ = expr->getCallee();
30 auto const ret = Base::TraverseCallExpr(expr);
31 callee_ = saved;
32 return ret;
35 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * expr) {
36 auto const saved = callee_;
37 callee_ = expr->getCallee();
38 auto const ret = Base::TraverseCXXOperatorCallExpr(expr);
39 callee_ = saved;
40 return ret;
43 bool TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr) {
44 auto const saved = callee_;
45 callee_ = expr->getCallee();
46 auto const ret = Base::TraverseCXXMemberCallExpr(expr);
47 callee_ = saved;
48 return ret;
51 bool TraverseCUDAKernelCallExpr(CUDAKernelCallExpr * expr) {
52 auto const saved = callee_;
53 callee_ = expr->getCallee();
54 auto const ret = Base::TraverseCUDAKernelCallExpr(expr);
55 callee_ = saved;
56 return ret;
59 bool TraverseUserDefinedLiteral(UserDefinedLiteral * expr) {
60 auto const saved = callee_;
61 callee_ = expr->getCallee();
62 auto const ret = Base::TraverseUserDefinedLiteral(expr);
63 callee_ = saved;
64 return ret;
67 bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) {
68 if (expr == callee_) {
69 return true;
71 if (this->ignoreLocation(expr)) {
72 return true;
74 if (expr->getCastKind() != CK_FunctionToPointerDecay) {
75 return true;
77 auto const dre = dyn_cast<DeclRefExpr>(
78 expr->getSubExpr()->IgnoreParens());
79 if (dre == nullptr) {
80 return true;
82 auto const fd = dyn_cast<FunctionDecl>(dre->getDecl());
83 if (fd == nullptr) {
84 return true;
86 ignoredFunctions_.insert(fd->getCanonicalDecl());
87 return true;
90 bool VisitUnaryOperator(UnaryOperator * expr) {
91 if (expr->getOpcode() != UO_AddrOf) {
92 return Base::VisitUnaryOperator(expr);
94 if (this->ignoreLocation(expr)) {
95 return true;
97 auto const dre = dyn_cast<DeclRefExpr>(
98 expr->getSubExpr()->IgnoreParenImpCasts());
99 if (dre == nullptr) {
100 return true;
102 auto const fd = dyn_cast<FunctionDecl>(dre->getDecl());
103 if (fd == nullptr) {
104 return true;
106 ignoredFunctions_.insert(fd->getCanonicalDecl());
107 return true;
110 protected:
111 std::unordered_set<FunctionDecl const *> const & getFunctionsWithAddressTaken() { return ignoredFunctions_; }
113 private:
114 std::unordered_set<FunctionDecl const *> ignoredFunctions_;
115 Expr const * callee_ = nullptr;
120 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */