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 template<std::size_t N
> ContextCheck
checkRecordDecl(
28 clang::Decl
const * decl
, clang::TagTypeKind tag
, char const (& id
)[N
]);
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 template<std::size_t N
> inline ContextCheck
Class(char const (& id
)[N
])
65 template<std::size_t N
> inline ContextCheck
Struct(char const (& id
)[N
])
68 TypeCheck
Typedef() const;
70 template<std::size_t N
> inline ContextCheck
Typedef(char const (& id
)[N
])
73 TypeCheck
NotSubstTemplateTypeParmType() const;
76 TypeCheck() = default;
78 clang::QualType
const type_
{};
83 explicit DeclCheck(clang::Decl
const * decl
): decl_(decl
) {}
85 explicit operator bool() const { return decl_
!= nullptr; }
87 template<std::size_t N
> inline ContextCheck
Class(char const (& id
)[N
])
90 template<std::size_t N
> inline ContextCheck
Struct(char const (& id
)[N
])
93 template<std::size_t N
> inline ContextCheck
Union(char const (& id
)[N
])
96 template<std::size_t N
> inline ContextCheck
Function(char const (& id
)[N
])
99 ContextCheck
Operator(clang::OverloadedOperatorKind op
) const;
101 template<std::size_t N
> inline ContextCheck
Var(char const (& id
)[N
])
104 ContextCheck
MemberFunction() const;
107 clang::Decl
const * const decl_
;
112 explicit operator bool() const { return context_
!= nullptr; }
114 TerminalCheck
GlobalNamespace() const;
116 template<std::size_t N
> inline ContextCheck
Namespace(
117 char const (& id
)[N
]) const;
119 TerminalCheck
StdNamespace() const;
121 ContextCheck
AnonymousNamespace() const;
123 template<std::size_t N
> inline ContextCheck
Class(char const (& id
)[N
])
126 template<std::size_t N
> inline ContextCheck
Struct(char const (& id
)[N
])
132 template<std::size_t N
> friend ContextCheck
detail::checkRecordDecl(
133 clang::Decl
const * decl
, clang::TagTypeKind tag
, char const (& id
)[N
]);
135 explicit ContextCheck(clang::DeclContext
const * context
= nullptr):
138 clang::DeclContext
const * const context_
;
141 class TerminalCheck
{
143 explicit operator bool() const { return satisfied_
; }
149 explicit TerminalCheck(bool satisfied
): satisfied_(satisfied
) {}
151 bool const satisfied_
;
156 template<std::size_t N
> ContextCheck
checkRecordDecl(
157 clang::Decl
const * decl
, clang::TagTypeKind tag
, char const (& id
)[N
])
159 auto r
= llvm::dyn_cast_or_null
<clang::RecordDecl
>(decl
);
160 if (r
!= nullptr && r
->getTagKind() == tag
) {
161 auto const i
= r
->getIdentifier();
162 if (i
!= nullptr && i
->isStr(id
)) {
163 return ContextCheck(r
->getDeclContext());
166 return ContextCheck();
171 template<std::size_t N
> ContextCheck
TypeCheck::Class(char const (& id
)[N
])
174 if (!type_
.isNull()) {
175 auto const t
= type_
->getAs
<clang::RecordType
>();
177 return detail::checkRecordDecl(t
->getDecl(), clang::TTK_Class
, id
);
180 return ContextCheck();
183 template<std::size_t N
> ContextCheck
TypeCheck::Struct(char const (& id
)[N
])
186 if (!type_
.isNull()) {
187 auto const t
= type_
->getAs
<clang::RecordType
>();
189 return detail::checkRecordDecl(t
->getDecl(), clang::TTK_Struct
, id
);
192 return ContextCheck();
195 template<std::size_t N
> ContextCheck
TypeCheck::Typedef(char const (& id
)[N
])
198 if (!type_
.isNull()) {
199 if (auto const t
= type_
->getAs
<clang::TypedefType
>()) {
200 auto const d
= t
->getDecl();
201 auto const i
= d
->getIdentifier();
202 assert(i
!= nullptr);
204 return ContextCheck(d
->getDeclContext());
208 return ContextCheck();
211 template<std::size_t N
> ContextCheck
DeclCheck::Class(char const (& id
)[N
])
214 return detail::checkRecordDecl(decl_
, clang::TTK_Class
, id
);
217 template<std::size_t N
> ContextCheck
DeclCheck::Struct(char const (& id
)[N
])
220 return detail::checkRecordDecl(decl_
, clang::TTK_Struct
, id
);
223 template<std::size_t N
> ContextCheck
DeclCheck::Union(char const (& id
)[N
])
226 return detail::checkRecordDecl(decl_
, clang::TTK_Union
, id
);
229 template<std::size_t N
> ContextCheck
DeclCheck::Function(char const (& id
)[N
])
232 auto f
= llvm::dyn_cast_or_null
<clang::FunctionDecl
>(decl_
);
234 auto const i
= f
->getIdentifier();
235 if (i
!= nullptr && i
->isStr(id
)) {
236 return ContextCheck(f
->getDeclContext());
239 return ContextCheck();
242 template<std::size_t N
> ContextCheck
DeclCheck::Var(char const (& id
)[N
])
245 auto f
= llvm::dyn_cast_or_null
<clang::VarDecl
>(decl_
);
247 auto const i
= f
->getIdentifier();
248 if (i
!= nullptr && i
->isStr(id
)) {
249 return ContextCheck(f
->getDeclContext());
252 return ContextCheck();
255 template<std::size_t N
> ContextCheck
ContextCheck::Namespace(
256 char const (& id
)[N
]) const
259 auto n
= llvm::dyn_cast
<clang::NamespaceDecl
>(context_
);
261 auto const i
= n
->getIdentifier();
262 if (i
!= nullptr && i
->isStr(id
)) {
263 return ContextCheck(n
->getParent());
267 return ContextCheck();
270 template<std::size_t N
> ContextCheck
ContextCheck::Class(char const (& id
)[N
])
273 return detail::checkRecordDecl(
274 llvm::dyn_cast_or_null
<clang::Decl
>(context_
), clang::TTK_Class
, id
);
277 template<std::size_t N
> ContextCheck
ContextCheck::Struct(char const (& id
)[N
])
280 return detail::checkRecordDecl(
281 llvm::dyn_cast_or_null
<clang::Decl
>(context_
), clang::TTK_Struct
, id
);
284 bool isExtraWarnUnusedType(clang::QualType type
);
286 bool isOkToRemoveArithmeticCast(
287 clang::ASTContext
& context
, clang::QualType t1
, clang::QualType t2
,
288 const clang::Expr
* subExpr
);
294 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */