Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / compilerplugins / clang / check.hxx
blob407258393eb8c3e4bbf390f04e2c25fb81e36c59
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 TypeCheck(clang::TypeDecl const * decl): type_(decl->getTypeForDecl(), 0) {}
38 explicit operator bool() const { return !type_.isNull(); }
40 TypeCheck NonConst() const;
42 TypeCheck NonConstVolatile() const;
44 TypeCheck Const() const;
46 TypeCheck Volatile() const;
48 TypeCheck ConstVolatile() const;
50 TerminalCheck Void() const;
52 TerminalCheck Char() const;
54 TerminalCheck AnyBoolean() const;
56 TypeCheck Pointer() const;
58 TerminalCheck Enum() const;
60 TypeCheck LvalueReference() const;
62 template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
63 const;
65 template<std::size_t N> inline ContextCheck Struct(char const (& id)[N])
66 const;
68 TypeCheck Typedef() const;
70 template<std::size_t N> inline ContextCheck Typedef(char const (& id)[N])
71 const;
73 TypeCheck NotSubstTemplateTypeParmType() const;
75 private:
76 TypeCheck() = default;
78 clang::QualType const type_{};
81 class DeclCheck {
82 public:
83 explicit DeclCheck(clang::Decl const * decl): decl_(decl) {}
85 explicit operator bool() const { return decl_ != nullptr; }
87 template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
88 const;
90 template<std::size_t N> inline ContextCheck Struct(char const (& id)[N])
91 const;
93 template<std::size_t N> inline ContextCheck Union(char const (& id)[N])
94 const;
96 template<std::size_t N> inline ContextCheck Function(char const (& id)[N])
97 const;
99 ContextCheck Operator(clang::OverloadedOperatorKind op) const;
101 template<std::size_t N> inline ContextCheck Var(char const (& id)[N])
102 const;
104 ContextCheck MemberFunction() const;
106 private:
107 clang::Decl const * const decl_;
110 class ContextCheck {
111 public:
112 explicit operator bool() const { return context_ != nullptr; }
114 TerminalCheck GlobalNamespace() const;
116 template<std::size_t N> inline ContextCheck Namespace(
117 char const (& id)[N]) const;
119 TerminalCheck StdNamespace() const;
121 ContextCheck AnonymousNamespace() const;
123 template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
124 const;
126 template<std::size_t N> inline ContextCheck Struct(char const (& id)[N])
127 const;
129 private:
130 friend DeclCheck;
131 friend TypeCheck;
132 template<std::size_t N> friend ContextCheck detail::checkRecordDecl(
133 clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]);
135 explicit ContextCheck(clang::DeclContext const * context = nullptr):
136 context_(context) {}
138 clang::DeclContext const * const context_;
141 class TerminalCheck {
142 public:
143 explicit operator bool() const { return satisfied_; }
145 private:
146 friend ContextCheck;
147 friend TypeCheck;
149 explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {}
151 bool const satisfied_;
154 namespace detail {
156 template<std::size_t N> ContextCheck checkRecordDecl(
157 clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N])
159 auto r = llvm::dyn_cast_or_null<clang::RecordDecl>(decl);
160 if (r != nullptr && r->getTagKind() == tag) {
161 auto const i = r->getIdentifier();
162 if (i != nullptr && i->isStr(id)) {
163 return ContextCheck(r->getDeclContext());
166 return ContextCheck();
171 template<std::size_t N> ContextCheck TypeCheck::Class(char const (& id)[N])
172 const
174 if (!type_.isNull()) {
175 auto const t = type_->getAs<clang::RecordType>();
176 if (t != nullptr) {
177 return detail::checkRecordDecl(t->getDecl(), clang::TTK_Class, id);
180 return ContextCheck();
183 template<std::size_t N> ContextCheck TypeCheck::Struct(char const (& id)[N])
184 const
186 if (!type_.isNull()) {
187 auto const t = type_->getAs<clang::RecordType>();
188 if (t != nullptr) {
189 return detail::checkRecordDecl(t->getDecl(), clang::TTK_Struct, id);
192 return ContextCheck();
195 template<std::size_t N> ContextCheck TypeCheck::Typedef(char const (& id)[N])
196 const
198 if (!type_.isNull()) {
199 if (auto const t = type_->getAs<clang::TypedefType>()) {
200 auto const d = t->getDecl();
201 auto const i = d->getIdentifier();
202 assert(i != nullptr);
203 if (i->isStr(id)) {
204 return ContextCheck(d->getDeclContext());
208 return ContextCheck();
211 template<std::size_t N> ContextCheck DeclCheck::Class(char const (& id)[N])
212 const
214 return detail::checkRecordDecl(decl_, clang::TTK_Class, id);
217 template<std::size_t N> ContextCheck DeclCheck::Struct(char const (& id)[N])
218 const
220 return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
223 template<std::size_t N> ContextCheck DeclCheck::Union(char const (& id)[N])
224 const
226 return detail::checkRecordDecl(decl_, clang::TTK_Union, id);
229 template<std::size_t N> ContextCheck DeclCheck::Function(char const (& id)[N])
230 const
232 auto f = llvm::dyn_cast_or_null<clang::FunctionDecl>(decl_);
233 if (f != nullptr) {
234 auto const i = f->getIdentifier();
235 if (i != nullptr && i->isStr(id)) {
236 return ContextCheck(f->getDeclContext());
239 return ContextCheck();
242 template<std::size_t N> ContextCheck DeclCheck::Var(char const (& id)[N])
243 const
245 auto f = llvm::dyn_cast_or_null<clang::VarDecl>(decl_);
246 if (f != nullptr) {
247 auto const i = f->getIdentifier();
248 if (i != nullptr && i->isStr(id)) {
249 return ContextCheck(f->getDeclContext());
252 return ContextCheck();
255 template<std::size_t N> ContextCheck ContextCheck::Namespace(
256 char const (& id)[N]) const
258 if (context_) {
259 auto n = llvm::dyn_cast<clang::NamespaceDecl>(context_);
260 if (n != nullptr) {
261 auto const i = n->getIdentifier();
262 if (i != nullptr && i->isStr(id)) {
263 return ContextCheck(n->getParent());
267 return ContextCheck();
270 template<std::size_t N> ContextCheck ContextCheck::Class(char const (& id)[N])
271 const
273 return detail::checkRecordDecl(
274 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Class, id);
277 template<std::size_t N> ContextCheck ContextCheck::Struct(char const (& id)[N])
278 const
280 return detail::checkRecordDecl(
281 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Struct, id);
284 bool isExtraWarnUnusedType(clang::QualType type);
286 bool isOkToRemoveArithmeticCast(
287 clang::ASTContext & context, clang::QualType t1, clang::QualType t2,
288 const clang::Expr* subExpr);
292 #endif
294 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */