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/.
14 #include <clang/AST/DeclBase.h>
15 #include <clang/AST/Decl.h>
16 #include <clang/AST/Type.h>
17 #include <clang/Basic/OperatorKinds.h>
28 inline ContextCheck
checkRecordDecl(
29 clang::Decl
const * decl
, clang::TagTypeKind tag
, llvm::StringRef id
);
37 explicit TypeCheck(clang::QualType type
): type_(type
) {}
39 explicit TypeCheck(clang::Type
const * type
): type_(type
, 0) {}
41 explicit TypeCheck(clang::TypeDecl
const * decl
): type_(decl
->getTypeForDecl(), 0) {}
43 explicit operator bool() const { return !type_
.isNull(); }
45 TypeCheck
NonConst() const;
47 TypeCheck
NonConstVolatile() const;
49 TypeCheck
Const() const;
51 TypeCheck
Volatile() const;
53 TypeCheck
ConstVolatile() const;
55 TypeCheck
ConstNonVolatile() const;
57 TerminalCheck
Void() const;
59 TerminalCheck
Char() const;
61 TerminalCheck
AnyBoolean() const;
63 TypeCheck
Pointer() const;
65 TerminalCheck
Enum() const;
67 TypeCheck
LvalueReference() const;
69 TypeCheck
RvalueReference() const;
71 inline ContextCheck
Class(llvm::StringRef id
) const;
73 inline ContextCheck
Struct(llvm::StringRef id
) const;
75 inline ContextCheck
ClassOrStruct(llvm::StringRef id
) const;
77 TypeCheck
Typedef() const;
79 inline ContextCheck
Typedef(llvm::StringRef id
) const;
81 DeclCheck
TemplateSpecializationClass() const;
83 TypeCheck
NotSubstTemplateTypeParmType() const;
86 TypeCheck() = default;
88 clang::QualType
const type_
{};
95 explicit DeclCheck(clang::Decl
const * decl
): decl_(decl
) {}
97 explicit operator bool() const { return decl_
!= nullptr; }
99 inline ContextCheck
Class(llvm::StringRef id
) const;
101 inline ContextCheck
Struct(llvm::StringRef id
) const;
103 inline ContextCheck
ClassOrStruct(llvm::StringRef id
) const;
105 inline ContextCheck
Union(llvm::StringRef id
) const;
107 inline ContextCheck
Function(llvm::StringRef id
) const;
109 ContextCheck
Operator(clang::OverloadedOperatorKind op
) const;
111 inline ContextCheck
Var(llvm::StringRef id
) const;
113 ContextCheck
MemberFunction() const;
116 DeclCheck() = default;
118 clang::Decl
const * const decl_
= nullptr;
123 explicit ContextCheck(clang::DeclContext
const * context
= nullptr):
126 explicit operator bool() const { return context_
!= nullptr; }
128 TerminalCheck
GlobalNamespace() const;
130 inline ContextCheck
Namespace(llvm::StringRef id
) const;
132 TerminalCheck
StdNamespace() const;
134 TerminalCheck
StdOrNestedNamespace() const;
136 ContextCheck
AnonymousNamespace() const;
138 inline ContextCheck
Class(llvm::StringRef id
) const;
140 inline ContextCheck
Struct(llvm::StringRef id
) const;
142 explicit ContextCheck(const clang::NamespaceDecl
* decl
) : context_( decl
) {}
145 clang::DeclContext
const * lookThroughLinkageSpec() const;
147 clang::DeclContext
const * const context_
;
150 class TerminalCheck
{
152 explicit operator bool() const { return satisfied_
; }
158 explicit TerminalCheck(bool satisfied
): satisfied_(satisfied
) {}
160 bool const satisfied_
;
164 typedef std::function
<bool(clang::Decl
const *)> DeclChecker
;
165 // Returns true if the class has a base matching the checker, or, when checkSelf is true, if the
166 // class itself matches.
167 bool isDerivedFrom(const clang::CXXRecordDecl
*decl
, DeclChecker base
, bool checkSelf
= true);
172 ContextCheck
checkRecordDecl(
173 clang::Decl
const * decl
, clang::TagTypeKind tag
, llvm::StringRef id
)
175 auto r
= llvm::dyn_cast_or_null
<clang::RecordDecl
>(decl
);
176 if (r
!= nullptr && r
->getTagKind() == tag
) {
177 auto const i
= r
->getIdentifier();
178 if (i
!= nullptr && i
->getName() == id
) {
179 return ContextCheck(r
->getDeclContext());
182 return ContextCheck();
187 ContextCheck
TypeCheck::Class(llvm::StringRef id
)
190 if (!type_
.isNull()) {
191 auto const t
= type_
->getAs
<clang::RecordType
>();
193 return detail::checkRecordDecl(t
->getDecl(), compat::TagTypeKind::Class
, id
);
196 return ContextCheck();
199 ContextCheck
TypeCheck::Struct(llvm::StringRef id
) const
201 if (!type_
.isNull()) {
202 auto const t
= type_
->getAs
<clang::RecordType
>();
204 return detail::checkRecordDecl(t
->getDecl(), compat::TagTypeKind::Struct
, id
);
207 return ContextCheck();
210 ContextCheck
TypeCheck::ClassOrStruct(llvm::StringRef id
) const
212 auto const c1
= Class(id
);
219 ContextCheck
TypeCheck::Typedef(llvm::StringRef id
) const
221 if (!type_
.isNull()) {
222 if (auto const t
= type_
->getAs
<clang::TypedefType
>()) {
223 auto const d
= t
->getDecl();
224 auto const i
= d
->getIdentifier();
225 assert(i
!= nullptr);
226 if (i
->getName() == id
) {
227 return ContextCheck(d
->getDeclContext());
231 return ContextCheck();
234 ContextCheck
DeclCheck::Class(llvm::StringRef id
) const
236 return detail::checkRecordDecl(decl_
, compat::TagTypeKind::Class
, id
);
239 ContextCheck
DeclCheck::Struct(llvm::StringRef id
) const
241 return detail::checkRecordDecl(decl_
, compat::TagTypeKind::Struct
, id
);
244 ContextCheck
DeclCheck::ClassOrStruct(llvm::StringRef id
) const
246 auto const c1
= Class(id
);
253 ContextCheck
DeclCheck::Union(llvm::StringRef id
) const
255 return detail::checkRecordDecl(decl_
, compat::TagTypeKind::Union
, id
);
258 ContextCheck
DeclCheck::Function(llvm::StringRef id
) const
260 auto f
= llvm::dyn_cast_or_null
<clang::FunctionDecl
>(decl_
);
262 auto const i
= f
->getIdentifier();
263 if (i
!= nullptr && i
->getName() == id
) {
264 return ContextCheck(f
->getDeclContext());
267 return ContextCheck();
270 ContextCheck
DeclCheck::Var(llvm::StringRef id
) const
272 auto f
= llvm::dyn_cast_or_null
<clang::VarDecl
>(decl_
);
274 auto const i
= f
->getIdentifier();
275 if (i
!= nullptr && i
->getName() == id
) {
276 return ContextCheck(f
->getDeclContext());
279 return ContextCheck();
282 ContextCheck
ContextCheck::Namespace(llvm::StringRef id
) const
285 auto n
= llvm::dyn_cast
<clang::NamespaceDecl
>(lookThroughLinkageSpec());
287 auto const i
= n
->getIdentifier();
288 if (i
!= nullptr && i
->getName() == id
) {
289 return ContextCheck(n
->getParent());
293 return ContextCheck();
296 ContextCheck
ContextCheck::Class(llvm::StringRef id
) const
298 return detail::checkRecordDecl(
299 llvm::dyn_cast_or_null
<clang::Decl
>(context_
), compat::TagTypeKind::Class
, id
);
302 ContextCheck
ContextCheck::Struct(llvm::StringRef id
) const
304 return detail::checkRecordDecl(
305 llvm::dyn_cast_or_null
<clang::Decl
>(context_
), compat::TagTypeKind::Struct
, id
);
308 bool isExtraWarnUnusedType(clang::QualType type
);
310 bool isOkToRemoveArithmeticCast(
311 clang::ASTContext
& context
, clang::QualType t1
, clang::QualType t2
,
312 const clang::Expr
* subExpr
);
316 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */