1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #ifndef INCLUDED_COMPILERPLUGINS_CLANG_CHECK_HXX
11 #define INCLUDED_COMPILERPLUGINS_CLANG_CHECK_HXX
15 #include <clang/AST/DeclBase.h>
16 #include <clang/AST/Decl.h>
17 #include <clang/AST/Type.h>
18 #include <clang/Basic/OperatorKinds.h>
27 inline ContextCheck
checkRecordDecl(
28 clang::Decl
const * decl
, clang::TagTypeKind tag
, llvm::StringRef id
);
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;
73 TypeCheck() = default;
75 clang::QualType
const type_
{};
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;
99 clang::Decl
const * const decl_
;
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
) {}
123 friend ContextCheck
detail::checkRecordDecl(
124 clang::Decl
const * decl
, clang::TagTypeKind tag
, llvm::StringRef id
);
126 explicit ContextCheck(clang::DeclContext
const * context
= nullptr):
129 clang::DeclContext
const * const context_
;
132 class TerminalCheck
{
134 explicit operator bool() const { return satisfied_
; }
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
);
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
)
171 if (!type_
.isNull()) {
172 auto const t
= type_
->getAs
<clang::RecordType
>();
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
>();
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_
);
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_
);
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
248 auto n
= llvm::dyn_cast
<clang::NamespaceDecl
>(context_
);
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
);
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */