1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "NonTrivialTypeInFfiChecker.h"
6 #include "CustomMatchers.h"
8 void NonTrivialTypeInFfiChecker::registerMatchers(MatchFinder
*AstMatcher
) {
9 AstMatcher
->addMatcher(functionDecl(isExternC()).bind("func"), this);
12 void NonTrivialTypeInFfiChecker::check(const MatchFinder::MatchResult
&Result
) {
13 static DenseSet
<const FunctionDecl
*> CheckedFunctionDecls
;
15 const FunctionDecl
*func
= Result
.Nodes
.getNodeAs
<FunctionDecl
>("func");
16 // Don't report errors on the same declarations more than once.
17 if (!CheckedFunctionDecls
.insert(func
).second
) {
21 if (inThirdPartyPath(func
)) {
25 auto NoteFor
= [](const QualType
&T
) -> std::string
{
26 std::string s
= "Please consider using a pointer or reference";
27 if (T
->getAs
<TemplateSpecializationType
>()) {
28 s
+= ", or explicitly instantiating the template";
30 return s
+ " instead";
33 for (ParmVarDecl
*p
: func
->parameters()) {
34 QualType T
= p
->getType().getUnqualifiedType();
35 if (!T
->isVoidType() && !T
->isReferenceType() &&
36 !T
.isTriviallyCopyableType(*Result
.Context
)) {
37 diag(p
->getLocation(),
38 "Type %0 must not be used as parameter to extern "
42 diag(p
->getLocation(), NoteFor(T
), DiagnosticIDs::Note
);
46 QualType T
= func
->getReturnType().getUnqualifiedType();
47 if (!T
->isVoidType() && !T
->isReferenceType() &&
48 !T
.isTriviallyCopyableType(*Result
.Context
)) {
49 diag(func
->getLocation(),
50 "Type %0 must not be used as return type of "
51 "extern \"C\" function",
54 diag(func
->getLocation(), NoteFor(T
), DiagnosticIDs::Note
);