nss: upgrade to release 3.73
[LibreOffice.git] / compilerplugins / clang / check.hxx
blob03c5ab1eb1e4223f17fdc301b7dd9b6cd3cadab9
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 inline ContextCheck Class(llvm::StringRef id) const;
69 inline ContextCheck Struct(llvm::StringRef id) const;
71 inline ContextCheck ClassOrStruct(llvm::StringRef id) const;
73 TypeCheck Typedef() const;
75 inline ContextCheck Typedef(llvm::StringRef id) const;
77 DeclCheck TemplateSpecializationClass() const;
79 TypeCheck NotSubstTemplateTypeParmType() const;
81 private:
82 TypeCheck() = default;
84 clang::QualType const type_{};
87 class DeclCheck {
88 friend TypeCheck;
90 public:
91 explicit DeclCheck(clang::Decl const * decl): decl_(decl) {}
93 explicit operator bool() const { return decl_ != nullptr; }
95 inline ContextCheck Class(llvm::StringRef id) const;
97 inline ContextCheck Struct(llvm::StringRef id) const;
99 inline ContextCheck ClassOrStruct(llvm::StringRef id) const;
101 inline ContextCheck Union(llvm::StringRef id) const;
103 inline ContextCheck Function(llvm::StringRef id) const;
105 ContextCheck Operator(clang::OverloadedOperatorKind op) const;
107 inline ContextCheck Var(llvm::StringRef id) const;
109 ContextCheck MemberFunction() const;
111 private:
112 DeclCheck() = default;
114 clang::Decl const * const decl_ = nullptr;
117 class ContextCheck {
118 public:
119 explicit ContextCheck(clang::DeclContext const * context = nullptr):
120 context_(context) {}
122 explicit operator bool() const { return context_ != nullptr; }
124 TerminalCheck GlobalNamespace() const;
126 inline ContextCheck Namespace(llvm::StringRef id) const;
128 TerminalCheck StdNamespace() const;
130 TerminalCheck StdOrNestedNamespace() const;
132 ContextCheck AnonymousNamespace() const;
134 inline ContextCheck Class(llvm::StringRef id) const;
136 inline ContextCheck Struct(llvm::StringRef id) const;
138 explicit ContextCheck(const clang::NamespaceDecl * decl ) : context_( decl ) {}
140 private:
141 clang::DeclContext const * const context_;
144 class TerminalCheck {
145 public:
146 explicit operator bool() const { return satisfied_; }
148 private:
149 friend ContextCheck;
150 friend TypeCheck;
152 explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {}
154 bool const satisfied_;
158 typedef std::function<bool(clang::Decl const *)> DeclChecker;
159 // Returns true if the class has a base matching the checker, or if the class itself matches.
160 bool isDerivedFrom(const clang::CXXRecordDecl *decl, DeclChecker base);
163 namespace detail {
165 ContextCheck checkRecordDecl(
166 clang::Decl const * decl, clang::TagTypeKind tag, llvm::StringRef id)
168 auto r = llvm::dyn_cast_or_null<clang::RecordDecl>(decl);
169 if (r != nullptr && r->getTagKind() == tag) {
170 auto const i = r->getIdentifier();
171 if (i != nullptr && i->getName() == id) {
172 return ContextCheck(r->getDeclContext());
175 return ContextCheck();
180 ContextCheck TypeCheck::Class(llvm::StringRef id)
181 const
183 if (!type_.isNull()) {
184 auto const t = type_->getAs<clang::RecordType>();
185 if (t != nullptr) {
186 return detail::checkRecordDecl(t->getDecl(), clang::TTK_Class, id);
189 return ContextCheck();
192 ContextCheck TypeCheck::Struct(llvm::StringRef id) const
194 if (!type_.isNull()) {
195 auto const t = type_->getAs<clang::RecordType>();
196 if (t != nullptr) {
197 return detail::checkRecordDecl(t->getDecl(), clang::TTK_Struct, id);
200 return ContextCheck();
203 ContextCheck TypeCheck::ClassOrStruct(llvm::StringRef id) const
205 auto const c1 = Class(id);
206 if (c1) {
207 return c1;
209 return Struct(id);
212 ContextCheck TypeCheck::Typedef(llvm::StringRef id) const
214 if (!type_.isNull()) {
215 if (auto const t = type_->getAs<clang::TypedefType>()) {
216 auto const d = t->getDecl();
217 auto const i = d->getIdentifier();
218 assert(i != nullptr);
219 if (i->getName() == id) {
220 return ContextCheck(d->getDeclContext());
224 return ContextCheck();
227 ContextCheck DeclCheck::Class(llvm::StringRef id) const
229 return detail::checkRecordDecl(decl_, clang::TTK_Class, id);
232 ContextCheck DeclCheck::Struct(llvm::StringRef id) const
234 return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
237 ContextCheck DeclCheck::ClassOrStruct(llvm::StringRef id) const
239 auto const c1 = Class(id);
240 if (c1) {
241 return c1;
243 return Struct(id);
246 ContextCheck DeclCheck::Union(llvm::StringRef id) const
248 return detail::checkRecordDecl(decl_, clang::TTK_Union, id);
251 ContextCheck DeclCheck::Function(llvm::StringRef id) const
253 auto f = llvm::dyn_cast_or_null<clang::FunctionDecl>(decl_);
254 if (f != nullptr) {
255 auto const i = f->getIdentifier();
256 if (i != nullptr && i->getName() == id) {
257 return ContextCheck(f->getDeclContext());
260 return ContextCheck();
263 ContextCheck DeclCheck::Var(llvm::StringRef id) const
265 auto f = llvm::dyn_cast_or_null<clang::VarDecl>(decl_);
266 if (f != nullptr) {
267 auto const i = f->getIdentifier();
268 if (i != nullptr && i->getName() == id) {
269 return ContextCheck(f->getDeclContext());
272 return ContextCheck();
275 ContextCheck ContextCheck::Namespace(llvm::StringRef id) const
277 if (context_) {
278 auto n = llvm::dyn_cast<clang::NamespaceDecl>(context_);
279 if (n != nullptr) {
280 auto const i = n->getIdentifier();
281 if (i != nullptr && i->getName() == id) {
282 return ContextCheck(n->getParent());
286 return ContextCheck();
289 ContextCheck ContextCheck::Class(llvm::StringRef id) const
291 return detail::checkRecordDecl(
292 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Class, id);
295 ContextCheck ContextCheck::Struct(llvm::StringRef id) const
297 return detail::checkRecordDecl(
298 llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Struct, id);
301 bool isExtraWarnUnusedType(clang::QualType type);
303 bool isOkToRemoveArithmeticCast(
304 clang::ASTContext & context, clang::QualType t1, clang::QualType t2,
305 const clang::Expr* subExpr);
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */