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 operator bool() const { return !type_
.isNull(); }
38 TypeCheck
Const() const;
40 TerminalCheck
Char() const;
42 TerminalCheck
AnyBoolean() const;
44 TypeCheck
Pointer() const;
46 TypeCheck
LvalueReference() const;
48 template<std::size_t N
> inline ContextCheck
Class(char const (& id
)[N
])
51 TypeCheck
Typedef() const;
53 template<std::size_t N
> inline ContextCheck
Typedef(char const (& id
)[N
])
56 TypeCheck
NotSubstTemplateTypeParmType() const;
59 TypeCheck() = default;
61 clang::QualType
const type_
;
66 explicit DeclCheck(clang::Decl
const * decl
): decl_(decl
) {}
68 explicit operator bool() const { return decl_
!= nullptr; }
70 template<std::size_t N
> inline ContextCheck
Class(char const (& id
)[N
])
73 template<std::size_t N
> inline ContextCheck
Struct(char const (& id
)[N
])
76 template<std::size_t N
> inline ContextCheck
Function(char const (& id
)[N
])
79 ContextCheck
Operator(clang::OverloadedOperatorKind op
) const;
81 template<std::size_t N
> inline ContextCheck
Var(char const (& id
)[N
])
84 ContextCheck
MemberFunction() const;
87 clang::Decl
const * const decl_
;
92 explicit operator bool() const { return context_
!= nullptr; }
94 TerminalCheck
GlobalNamespace() const;
96 template<std::size_t N
> inline ContextCheck
Namespace(
97 char const (& id
)[N
]) const;
99 TerminalCheck
StdNamespace() const;
101 ContextCheck
AnonymousNamespace() const;
103 template<std::size_t N
> inline ContextCheck
Class(char const (& id
)[N
])
106 template<std::size_t N
> inline ContextCheck
Struct(char const (& id
)[N
])
112 template<std::size_t N
> friend ContextCheck
detail::checkRecordDecl(
113 clang::Decl
const * decl
, clang::TagTypeKind tag
, char const (& id
)[N
]);
115 explicit ContextCheck(clang::DeclContext
const * context
= nullptr):
118 clang::DeclContext
const * const context_
;
121 class TerminalCheck
{
123 explicit operator bool() const { return satisfied_
; }
129 explicit TerminalCheck(bool satisfied
): satisfied_(satisfied
) {}
131 bool const satisfied_
;
136 template<std::size_t N
> ContextCheck
checkRecordDecl(
137 clang::Decl
const * decl
, clang::TagTypeKind tag
, char const (& id
)[N
])
139 auto r
= llvm::dyn_cast_or_null
<clang::RecordDecl
>(decl
);
140 if (r
!= nullptr && r
->getTagKind() == tag
) {
141 auto const i
= r
->getIdentifier();
142 if (i
!= nullptr && i
->isStr(id
)) {
143 return ContextCheck(r
->getDeclContext());
146 return ContextCheck();
151 template<std::size_t N
> ContextCheck
TypeCheck::Class(char const (& id
)[N
])
154 if (!type_
.isNull()) {
155 auto const t
= type_
->getAs
<clang::RecordType
>();
157 return detail::checkRecordDecl(t
->getDecl(), clang::TTK_Class
, id
);
160 return ContextCheck();
163 template<std::size_t N
> ContextCheck
TypeCheck::Typedef(char const (& id
)[N
])
166 if (!type_
.isNull()) {
167 if (auto const t
= type_
->getAs
<clang::TypedefType
>()) {
168 auto const d
= t
->getDecl();
169 auto const i
= d
->getIdentifier();
170 assert(i
!= nullptr);
172 return ContextCheck(d
->getDeclContext());
176 return ContextCheck();
179 template<std::size_t N
> ContextCheck
DeclCheck::Class(char const (& id
)[N
])
182 return detail::checkRecordDecl(decl_
, clang::TTK_Class
, id
);
185 template<std::size_t N
> ContextCheck
DeclCheck::Struct(char const (& id
)[N
])
188 return detail::checkRecordDecl(decl_
, clang::TTK_Struct
, id
);
191 template<std::size_t N
> ContextCheck
DeclCheck::Function(char const (& id
)[N
])
194 auto f
= llvm::dyn_cast_or_null
<clang::FunctionDecl
>(decl_
);
196 auto const i
= f
->getIdentifier();
197 if (i
!= nullptr && i
->isStr(id
)) {
198 return ContextCheck(f
->getDeclContext());
201 return ContextCheck();
204 template<std::size_t N
> ContextCheck
DeclCheck::Var(char const (& id
)[N
])
207 auto f
= llvm::dyn_cast_or_null
<clang::VarDecl
>(decl_
);
209 auto const i
= f
->getIdentifier();
210 if (i
!= nullptr && i
->isStr(id
)) {
211 return ContextCheck(f
->getDeclContext());
214 return ContextCheck();
217 template<std::size_t N
> ContextCheck
ContextCheck::Namespace(
218 char const (& id
)[N
]) const
221 auto n
= llvm::dyn_cast
<clang::NamespaceDecl
>(context_
);
223 auto const i
= n
->getIdentifier();
224 if (i
!= nullptr && i
->isStr(id
)) {
225 return ContextCheck(n
->getParent());
229 return ContextCheck();
232 template<std::size_t N
> ContextCheck
ContextCheck::Class(char const (& id
)[N
])
235 return detail::checkRecordDecl(
236 llvm::dyn_cast_or_null
<clang::Decl
>(context_
), clang::TTK_Class
, id
);
239 template<std::size_t N
> ContextCheck
ContextCheck::Struct(char const (& id
)[N
])
242 return detail::checkRecordDecl(
243 llvm::dyn_cast_or_null
<clang::Decl
>(context_
), clang::TTK_Struct
, id
);
250 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */