Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / compilerplugins / clang / check.hxx
bloba7b7ba820d0949d411f0c99efafae65f2e5cfb21
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 <cstddef>
14 #include <clang/AST/DeclBase.h>
15 #include <clang/AST/Decl.h>
16 #include <clang/AST/Type.h>
17 #include <clang/Basic/OperatorKinds.h>
19 namespace loplugin {
21 class ContextCheck;
22 class TerminalCheck;
24 namespace detail {
26 inline ContextCheck checkRecordDecl(
27 clang::Decl const * decl, clang::TagTypeKind tag, llvm::StringRef id);
31 class DeclCheck;
33 class TypeCheck {
34 public:
35 explicit TypeCheck(clang::QualType type): type_(type) {}
37 explicit TypeCheck(clang::Type const * type): type_(type, 0) {}
39 explicit TypeCheck(clang::TypeDecl const * decl): type_(decl->getTypeForDecl(), 0) {}
41 explicit operator bool() const { return !type_.isNull(); }
43 TypeCheck NonConst() const;
45 TypeCheck NonConstVolatile() const;
47 TypeCheck Const() const;
49 TypeCheck Volatile() const;
51 TypeCheck ConstVolatile() const;
53 TypeCheck ConstNonVolatile() const;
55 TerminalCheck Void() const;
57 TerminalCheck Char() const;
59 TerminalCheck AnyBoolean() const;
61 TypeCheck Pointer() const;
63 TerminalCheck Enum() const;
65 TypeCheck LvalueReference() const;
67 TypeCheck RvalueReference() const;
69 inline ContextCheck Class(llvm::StringRef id) const;
71 inline ContextCheck Struct(llvm::StringRef id) const;
73 inline ContextCheck ClassOrStruct(llvm::StringRef id) const;
75 TypeCheck Typedef() const;
77 inline ContextCheck Typedef(llvm::StringRef id) const;
79 DeclCheck TemplateSpecializationClass() const;
81 TypeCheck NotSubstTemplateTypeParmType() const;
83 private:
84 TypeCheck() = default;
86 clang::QualType const type_{};
89 class DeclCheck {
90 friend TypeCheck;
92 public:
93 explicit DeclCheck(clang::Decl const * decl): decl_(decl) {}
95 explicit operator bool() const { return decl_ != nullptr; }
97 inline ContextCheck Class(llvm::StringRef id) const;
99 inline ContextCheck Struct(llvm::StringRef id) const;
101 inline ContextCheck ClassOrStruct(llvm::StringRef id) const;
103 inline ContextCheck Union(llvm::StringRef id) const;
105 inline ContextCheck Function(llvm::StringRef id) const;
107 ContextCheck Operator(clang::OverloadedOperatorKind op) const;
109 inline ContextCheck Var(llvm::StringRef id) const;
111 ContextCheck MemberFunction() const;
113 private:
114 DeclCheck() = default;
116 clang::Decl const * const decl_ = nullptr;
119 class ContextCheck {
120 public:
121 explicit ContextCheck(clang::DeclContext const * context = nullptr):
122 context_(context) {}
124 explicit operator bool() const { return context_ != nullptr; }
126 TerminalCheck GlobalNamespace() const;
128 inline ContextCheck Namespace(llvm::StringRef id) const;
130 TerminalCheck StdNamespace() const;
132 TerminalCheck StdOrNestedNamespace() const;
134 ContextCheck AnonymousNamespace() const;
136 inline ContextCheck Class(llvm::StringRef id) const;
138 inline ContextCheck Struct(llvm::StringRef id) const;
140 explicit ContextCheck(const clang::NamespaceDecl * decl ) : context_( decl ) {}
142 private:
143 clang::DeclContext const * lookThroughLinkageSpec() const;
145 clang::DeclContext const * const context_;
148 class TerminalCheck {
149 public:
150 explicit operator bool() const { return satisfied_; }
152 private:
153 friend ContextCheck;
154 friend TypeCheck;
156 explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {}
158 bool const satisfied_;
162 typedef std::function<bool(clang::Decl const *)> DeclChecker;
163 // Returns true if the class has a base matching the checker, or, when checkSelf is true, if the
164 // class itself matches.
165 bool isDerivedFrom(const clang::CXXRecordDecl *decl, DeclChecker base, bool checkSelf = true);
168 namespace detail {
170 ContextCheck checkRecordDecl(
171 clang::Decl const * decl, clang::TagTypeKind tag, llvm::StringRef id)
173 auto r = llvm::dyn_cast_or_null<clang::RecordDecl>(decl);
174 if (r != nullptr && r->getTagKind() == tag) {
175 auto const i = r->getIdentifier();
176 if (i != nullptr && i->getName() == id) {
177 return ContextCheck(r->getDeclContext());
180 return ContextCheck();
185 ContextCheck TypeCheck::Class(llvm::StringRef id)
186 const
188 if (!type_.isNull()) {
189 auto const t = type_->getAs<clang::RecordType>();
190 if (t != nullptr) {
191 return detail::checkRecordDecl(t->getDecl(), clang::TTK_Class, id);
194 return ContextCheck();
197 ContextCheck TypeCheck::Struct(llvm::StringRef id) const
199 if (!type_.isNull()) {
200 auto const t = type_->getAs<clang::RecordType>();
201 if (t != nullptr) {
202 return detail::checkRecordDecl(t->getDecl(), clang::TTK_Struct, id);
205 return ContextCheck();
208 ContextCheck TypeCheck::ClassOrStruct(llvm::StringRef id) const
210 auto const c1 = Class(id);
211 if (c1) {
212 return c1;
214 return Struct(id);
217 ContextCheck TypeCheck::Typedef(llvm::StringRef id) const
219 if (!type_.isNull()) {
220 if (auto const t = type_->getAs<clang::TypedefType>()) {
221 auto const d = t->getDecl();
222 auto const i = d->getIdentifier();
223 assert(i != nullptr);
224 if (i->getName() == id) {
225 return ContextCheck(d->getDeclContext());
229 return ContextCheck();
232 ContextCheck DeclCheck::Class(llvm::StringRef id) const
234 return detail::checkRecordDecl(decl_, clang::TTK_Class, id);
237 ContextCheck DeclCheck::Struct(llvm::StringRef id) const
239 return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
242 ContextCheck DeclCheck::ClassOrStruct(llvm::StringRef id) const
244 auto const c1 = Class(id);
245 if (c1) {
246 return c1;
248 return Struct(id);
251 ContextCheck DeclCheck::Union(llvm::StringRef id) const
253 return detail::checkRecordDecl(decl_, clang::TTK_Union, id);
256 ContextCheck DeclCheck::Function(llvm::StringRef id) const
258 auto f = llvm::dyn_cast_or_null<clang::FunctionDecl>(decl_);
259 if (f != nullptr) {
260 auto const i = f->getIdentifier();
261 if (i != nullptr && i->getName() == id) {
262 return ContextCheck(f->getDeclContext());
265 return ContextCheck();
268 ContextCheck DeclCheck::Var(llvm::StringRef id) const
270 auto f = llvm::dyn_cast_or_null<clang::VarDecl>(decl_);
271 if (f != nullptr) {
272 auto const i = f->getIdentifier();
273 if (i != nullptr && i->getName() == id) {
274 return ContextCheck(f->getDeclContext());
277 return ContextCheck();
280 ContextCheck ContextCheck::Namespace(llvm::StringRef id) const
282 if (context_) {
283 auto n = llvm::dyn_cast<clang::NamespaceDecl>(lookThroughLinkageSpec());
284 if (n != nullptr) {
285 auto const i = n->getIdentifier();
286 if (i != nullptr && i->getName() == id) {
287 return ContextCheck(n->getParent());
291 return ContextCheck();
294 ContextCheck ContextCheck::Class(llvm::StringRef id) const
296 return detail::checkRecordDecl(
297 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Class, id);
300 ContextCheck ContextCheck::Struct(llvm::StringRef id) const
302 return detail::checkRecordDecl(
303 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Struct, id);
306 bool isExtraWarnUnusedType(clang::QualType type);
308 bool isOkToRemoveArithmeticCast(
309 clang::ASTContext & context, clang::QualType t1, clang::QualType t2,
310 const clang::Expr* subExpr);
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */