cURL: follow redirects
[LibreOffice.git] / compilerplugins / clang / check.hxx
blob9bfc458354a716b8d0ed1c58f849bd1f148ca022
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_CHECK_HXX
11 #define INCLUDED_COMPILERPLUGINS_CLANG_CHECK_HXX
13 #include <cstddef>
15 #include <clang/AST/DeclBase.h>
16 #include <clang/AST/Decl.h>
17 #include <clang/AST/Type.h>
18 #include <clang/Basic/OperatorKinds.h>
20 namespace loplugin {
22 class ContextCheck;
23 class TerminalCheck;
25 namespace detail {
27 template<std::size_t N> ContextCheck checkRecordDecl(
28 clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]);
32 class TypeCheck {
33 public:
34 explicit TypeCheck(clang::QualType type): type_(type) {}
36 explicit operator bool() const { return !type_.isNull(); }
38 TypeCheck Const() const;
40 TerminalCheck Char() const;
42 TerminalCheck AnyBoolean() const;
44 TypeCheck Pointer() const;
46 TypeCheck LvalueReference() const;
48 template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
49 const;
51 TypeCheck Typedef() const;
53 template<std::size_t N> inline ContextCheck Typedef(char const (& id)[N])
54 const;
56 TypeCheck NotSubstTemplateTypeParmType() const;
58 private:
59 TypeCheck() = default;
61 clang::QualType const type_;
64 class DeclCheck {
65 public:
66 explicit DeclCheck(clang::Decl const * decl): decl_(decl) {}
68 explicit operator bool() const { return decl_ != nullptr; }
70 template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
71 const;
73 template<std::size_t N> inline ContextCheck Struct(char const (& id)[N])
74 const;
76 template<std::size_t N> inline ContextCheck Function(char const (& id)[N])
77 const;
79 ContextCheck Operator(clang::OverloadedOperatorKind op) const;
81 template<std::size_t N> inline ContextCheck Var(char const (& id)[N])
82 const;
84 ContextCheck MemberFunction() const;
86 private:
87 clang::Decl const * const decl_;
90 class ContextCheck {
91 public:
92 explicit operator bool() const { return context_ != nullptr; }
94 TerminalCheck GlobalNamespace() const;
96 template<std::size_t N> inline ContextCheck Namespace(
97 char const (& id)[N]) const;
99 TerminalCheck StdNamespace() const;
101 ContextCheck AnonymousNamespace() const;
103 template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
104 const;
106 template<std::size_t N> inline ContextCheck Struct(char const (& id)[N])
107 const;
109 private:
110 friend DeclCheck;
111 friend TypeCheck;
112 template<std::size_t N> friend ContextCheck detail::checkRecordDecl(
113 clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]);
115 explicit ContextCheck(clang::DeclContext const * context = nullptr):
116 context_(context) {}
118 clang::DeclContext const * const context_;
121 class TerminalCheck {
122 public:
123 explicit operator bool() const { return satisfied_; }
125 private:
126 friend ContextCheck;
127 friend TypeCheck;
129 explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {}
131 bool const satisfied_;
134 namespace detail {
136 template<std::size_t N> ContextCheck checkRecordDecl(
137 clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N])
139 auto r = llvm::dyn_cast_or_null<clang::RecordDecl>(decl);
140 if (r != nullptr && r->getTagKind() == tag) {
141 auto const i = r->getIdentifier();
142 if (i != nullptr && i->isStr(id)) {
143 return ContextCheck(r->getDeclContext());
146 return ContextCheck();
151 template<std::size_t N> ContextCheck TypeCheck::Class(char const (& id)[N])
152 const
154 if (!type_.isNull()) {
155 auto const t = type_->getAs<clang::RecordType>();
156 if (t != nullptr) {
157 return detail::checkRecordDecl(t->getDecl(), clang::TTK_Class, id);
160 return ContextCheck();
163 template<std::size_t N> ContextCheck TypeCheck::Typedef(char const (& id)[N])
164 const
166 if (!type_.isNull()) {
167 if (auto const t = type_->getAs<clang::TypedefType>()) {
168 auto const d = t->getDecl();
169 auto const i = d->getIdentifier();
170 assert(i != nullptr);
171 if (i->isStr(id)) {
172 return ContextCheck(d->getDeclContext());
176 return ContextCheck();
179 template<std::size_t N> ContextCheck DeclCheck::Class(char const (& id)[N])
180 const
182 return detail::checkRecordDecl(decl_, clang::TTK_Class, id);
185 template<std::size_t N> ContextCheck DeclCheck::Struct(char const (& id)[N])
186 const
188 return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
191 template<std::size_t N> ContextCheck DeclCheck::Function(char const (& id)[N])
192 const
194 auto f = llvm::dyn_cast_or_null<clang::FunctionDecl>(decl_);
195 if (f != nullptr) {
196 auto const i = f->getIdentifier();
197 if (i != nullptr && i->isStr(id)) {
198 return ContextCheck(f->getDeclContext());
201 return ContextCheck();
204 template<std::size_t N> ContextCheck DeclCheck::Var(char const (& id)[N])
205 const
207 auto f = llvm::dyn_cast_or_null<clang::VarDecl>(decl_);
208 if (f != nullptr) {
209 auto const i = f->getIdentifier();
210 if (i != nullptr && i->isStr(id)) {
211 return ContextCheck(f->getDeclContext());
214 return ContextCheck();
217 template<std::size_t N> ContextCheck ContextCheck::Namespace(
218 char const (& id)[N]) const
220 if (context_) {
221 auto n = llvm::dyn_cast<clang::NamespaceDecl>(context_);
222 if (n != nullptr) {
223 auto const i = n->getIdentifier();
224 if (i != nullptr && i->isStr(id)) {
225 return ContextCheck(n->getParent());
229 return ContextCheck();
232 template<std::size_t N> ContextCheck ContextCheck::Class(char const (& id)[N])
233 const
235 return detail::checkRecordDecl(
236 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Class, id);
239 template<std::size_t N> ContextCheck ContextCheck::Struct(char const (& id)[N])
240 const
242 return detail::checkRecordDecl(
243 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Struct, id);
248 #endif
250 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */