bump product version to 6.3.0.0.beta1
[LibreOffice.git] / compilerplugins / clang / check.hxx
blobfd4d46fd0b97d97b6af62e159e7633a457864e23
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 inline ContextCheck checkRecordDecl(
28 clang::Decl const * decl, clang::TagTypeKind tag, llvm::StringRef id);
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 inline ContextCheck Class(llvm::StringRef id) const;
64 inline ContextCheck Struct(llvm::StringRef id) const;
66 TypeCheck Typedef() const;
68 inline ContextCheck Typedef(llvm::StringRef id) const;
70 TypeCheck NotSubstTemplateTypeParmType() const;
72 private:
73 TypeCheck() = default;
75 clang::QualType const type_{};
78 class DeclCheck {
79 public:
80 explicit DeclCheck(clang::Decl const * decl): decl_(decl) {}
82 explicit operator bool() const { return decl_ != nullptr; }
84 inline ContextCheck Class(llvm::StringRef id) const;
86 inline ContextCheck Struct(llvm::StringRef id) const;
88 inline ContextCheck Union(llvm::StringRef id) const;
90 inline ContextCheck Function(llvm::StringRef id) const;
92 ContextCheck Operator(clang::OverloadedOperatorKind op) const;
94 inline ContextCheck Var(llvm::StringRef id) const;
96 ContextCheck MemberFunction() const;
98 private:
99 clang::Decl const * const decl_;
102 class ContextCheck {
103 public:
104 explicit operator bool() const { return context_ != nullptr; }
106 TerminalCheck GlobalNamespace() const;
108 inline ContextCheck Namespace(llvm::StringRef id) const;
110 TerminalCheck StdNamespace() const;
112 ContextCheck AnonymousNamespace() const;
114 inline ContextCheck Class(llvm::StringRef id) const;
116 inline ContextCheck Struct(llvm::StringRef id) const;
118 explicit ContextCheck(const clang::NamespaceDecl * decl ) : context_( decl ) {}
120 private:
121 friend DeclCheck;
122 friend TypeCheck;
123 friend ContextCheck detail::checkRecordDecl(
124 clang::Decl const * decl, clang::TagTypeKind tag, llvm::StringRef id);
126 explicit ContextCheck(clang::DeclContext const * context = nullptr):
127 context_(context) {}
129 clang::DeclContext const * const context_;
132 class TerminalCheck {
133 public:
134 explicit operator bool() const { return satisfied_; }
136 private:
137 friend ContextCheck;
138 friend TypeCheck;
140 explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {}
142 bool const satisfied_;
146 typedef std::function<bool(clang::Decl const *)> DeclChecker;
147 // Returns true if the class has a base matching the checker, or if the class itself matches.
148 bool isDerivedFrom(const clang::CXXRecordDecl *decl, DeclChecker base);
151 namespace detail {
153 ContextCheck checkRecordDecl(
154 clang::Decl const * decl, clang::TagTypeKind tag, llvm::StringRef id)
156 auto r = llvm::dyn_cast_or_null<clang::RecordDecl>(decl);
157 if (r != nullptr && r->getTagKind() == tag) {
158 auto const i = r->getIdentifier();
159 if (i != nullptr && i->getName() == id) {
160 return ContextCheck(r->getDeclContext());
163 return ContextCheck();
168 ContextCheck TypeCheck::Class(llvm::StringRef id)
169 const
171 if (!type_.isNull()) {
172 auto const t = type_->getAs<clang::RecordType>();
173 if (t != nullptr) {
174 return detail::checkRecordDecl(t->getDecl(), clang::TTK_Class, id);
177 return ContextCheck();
180 ContextCheck TypeCheck::Struct(llvm::StringRef id) const
182 if (!type_.isNull()) {
183 auto const t = type_->getAs<clang::RecordType>();
184 if (t != nullptr) {
185 return detail::checkRecordDecl(t->getDecl(), clang::TTK_Struct, id);
188 return ContextCheck();
191 ContextCheck TypeCheck::Typedef(llvm::StringRef id) const
193 if (!type_.isNull()) {
194 if (auto const t = type_->getAs<clang::TypedefType>()) {
195 auto const d = t->getDecl();
196 auto const i = d->getIdentifier();
197 assert(i != nullptr);
198 if (i->getName() == id) {
199 return ContextCheck(d->getDeclContext());
203 return ContextCheck();
206 ContextCheck DeclCheck::Class(llvm::StringRef id) const
208 return detail::checkRecordDecl(decl_, clang::TTK_Class, id);
211 ContextCheck DeclCheck::Struct(llvm::StringRef id) const
213 return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
216 ContextCheck DeclCheck::Union(llvm::StringRef id) const
218 return detail::checkRecordDecl(decl_, clang::TTK_Union, id);
221 ContextCheck DeclCheck::Function(llvm::StringRef id) const
223 auto f = llvm::dyn_cast_or_null<clang::FunctionDecl>(decl_);
224 if (f != nullptr) {
225 auto const i = f->getIdentifier();
226 if (i != nullptr && i->getName() == id) {
227 return ContextCheck(f->getDeclContext());
230 return ContextCheck();
233 ContextCheck DeclCheck::Var(llvm::StringRef id) const
235 auto f = llvm::dyn_cast_or_null<clang::VarDecl>(decl_);
236 if (f != nullptr) {
237 auto const i = f->getIdentifier();
238 if (i != nullptr && i->getName() == id) {
239 return ContextCheck(f->getDeclContext());
242 return ContextCheck();
245 ContextCheck ContextCheck::Namespace(llvm::StringRef id) const
247 if (context_) {
248 auto n = llvm::dyn_cast<clang::NamespaceDecl>(context_);
249 if (n != nullptr) {
250 auto const i = n->getIdentifier();
251 if (i != nullptr && i->getName() == id) {
252 return ContextCheck(n->getParent());
256 return ContextCheck();
259 ContextCheck ContextCheck::Class(llvm::StringRef id) const
261 return detail::checkRecordDecl(
262 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Class, id);
265 ContextCheck ContextCheck::Struct(llvm::StringRef id) const
267 return detail::checkRecordDecl(
268 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Struct, id);
271 bool isExtraWarnUnusedType(clang::QualType type);
273 bool isOkToRemoveArithmeticCast(
274 clang::ASTContext & context, clang::QualType t1, clang::QualType t2,
275 const clang::Expr* subExpr);
279 #endif
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */