10 #include "../utils/OptionsUtils.h"
11 #include "clang/AST/DeclBase.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/ASTMatchers/ASTMatchers.h"
22 NonConstReferences::NonConstReferences(StringRef
Name,
36 unless(isInstantiated()),
38 qualType(unless(isConstQualified())).bind(
"referenced_type"))),
39 unless(hasType(rValueReferenceType())))
45 const auto *Parameter = Result.Nodes.getNodeAs<ParmVarDecl>(
"param");
46 const auto *Function =
47 dyn_cast_or_null<FunctionDecl>(Parameter->getParentFunctionOrMethod());
49 if (Function ==
nullptr || Function->isImplicit())
52 if (Function->getLocation().isMacroID())
55 if (!Function->isCanonicalDecl())
58 if (
const auto *Method = dyn_cast<CXXMethodDecl>(Function)) {
60 if (Method->begin_overridden_methods() != Method->end_overridden_methods())
64 if (Method->getParent()->isLambda())
68 auto ReferencedType = *Result.Nodes.getNodeAs<QualType>(
"referenced_type");
70 if (std::find_if(IncludedTypes.begin(), IncludedTypes.end(),
71 [&](llvm::StringRef ExplicitType) {
72 return ReferencedType.getCanonicalType().getAsString(
73 Result.Context->getPrintingPolicy()) ==
75 }) != IncludedTypes.end())
79 if (ReferencedType->isFunctionProtoType())
83 if (ReferencedType->isDependentType())
86 if (Function->isOverloadedOperator()) {
87 switch (Function->getOverloadedOperator()) {
88 case clang::OO_LessLess:
89 case clang::OO_PlusPlus:
90 case clang::OO_MinusMinus:
91 case clang::OO_PlusEqual:
92 case clang::OO_MinusEqual:
93 case clang::OO_StarEqual:
94 case clang::OO_SlashEqual:
95 case clang::OO_PercentEqual:
96 case clang::OO_LessLessEqual:
97 case clang::OO_GreaterGreaterEqual:
98 case clang::OO_PipeEqual:
99 case clang::OO_CaretEqual:
100 case clang::OO_AmpEqual:
103 if (Function->getParamDecl(0) == Parameter)
106 case clang::OO_GreaterGreater: {
107 auto isNonConstRef = [](clang::QualType T) {
108 return T->isReferenceType() &&
109 !T.getNonReferenceType().isConstQualified();
114 if (isNonConstRef(Function->getParamDecl(0)->getType()) &&
115 (Function->getNumParams() < 2 ||
116 isNonConstRef(Function->getParamDecl(1)->getType())) &&
117 isNonConstRef(Function->getReturnType()))
127 if (Function->getDeclName().isIdentifier() && Function->getName() ==
"swap")
131 if (StringRef(ReferencedType.getAsString()).endswith(
"stream"))
134 if (Parameter->getName().empty()) {
135 diag(Parameter->getLocation(),
"non-const reference parameter at index %0, "
136 "make it const or use a pointer")
137 << Parameter->getFunctionScopeIndex();
139 diag(Parameter->getLocation(),
140 "non-const reference parameter %0, make it const or use a pointer")