11 #include "clang/AST/DeclBase.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/ASTMatchers/ASTMatchers.h"
15 using namespace clang::ast_matchers;
22 void NonConstReferences::registerMatchers(MatchFinder *
Finder) {
25 unless(isInstantiated()),
27 qualType(unless(isConstQualified())).bind(
"referenced_type"))),
28 unless(hasType(rValueReferenceType())))
33 void NonConstReferences::check(
const MatchFinder::MatchResult &
Result) {
34 const auto *Parameter = Result.Nodes.getNodeAs<ParmVarDecl>(
"param");
35 const auto *Function =
36 dyn_cast_or_null<FunctionDecl>(Parameter->getParentFunctionOrMethod());
38 if (Function ==
nullptr || Function->isImplicit())
41 if (!Function->isCanonicalDecl())
44 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
46 if (Method->begin_overridden_methods() != Method->end_overridden_methods())
50 if (Method->getParent()->isLambda())
54 auto ReferencedType = *Result.Nodes.getNodeAs<QualType>(
"referenced_type");
56 if (ReferencedType->isFunctionProtoType())
60 if (ReferencedType->isDependentType())
63 if (Function->isOverloadedOperator()) {
64 switch (Function->getOverloadedOperator()) {
65 case clang::OO_LessLess:
66 case clang::OO_PlusPlus:
67 case clang::OO_MinusMinus:
68 case clang::OO_PlusEqual:
69 case clang::OO_MinusEqual:
70 case clang::OO_StarEqual:
71 case clang::OO_SlashEqual:
72 case clang::OO_PercentEqual:
73 case clang::OO_LessLessEqual:
74 case clang::OO_GreaterGreaterEqual:
75 case clang::OO_PipeEqual:
76 case clang::OO_CaretEqual:
77 case clang::OO_AmpEqual:
80 if (Function->getParamDecl(0) == Parameter)
83 case clang::OO_GreaterGreater: {
84 auto isNonConstRef = [](clang::QualType T) {
85 return T->isReferenceType() &&
86 !T.getNonReferenceType().isConstQualified();
91 if (isNonConstRef(Function->getParamDecl(0)->getType()) &&
92 (Function->getNumParams() < 2 ||
93 isNonConstRef(Function->getParamDecl(1)->getType())) &&
94 isNonConstRef(Function->getReturnType()))
104 if (Function->getDeclName().isIdentifier() && Function->getName() ==
"swap")
108 if (StringRef(ReferencedType.getAsString()).endswith(
"stream"))
111 if (Parameter->getName().empty()) {
112 diag(Parameter->getLocation(),
113 "non-const reference parameter at index %0, "
114 "make it const or use a pointer")
115 << Parameter->getFunctionScopeIndex();
117 diag(Parameter->getLocation(),
118 "non-const reference parameter %0, make it const or use a pointer")
std::unique_ptr< ast_matchers::MatchFinder > Finder