28 const auto DRef = ignoringParens(
30 to(parmVarDecl(hasType(hasCanonicalType(
31 qualType(lValueReferenceType(pointee(
32 qualType(isConstQualified()))))
34 hasDeclContext(functionDecl(
35 equalsBoundNode(
"func"),
36 hasReturnTypeLoc(loc(qualType(
37 hasCanonicalType(equalsBoundNode(
"type"))))))),
38 unless(hasLifetimeBoundAttr()))
44 hasAncestor(functionDecl().bind(
"func")),
46 DRef, ignoringParens(conditionalOperator(eachOf(
47 hasTrueExpression(DRef), hasFalseExpression(DRef))))))),
61 const ParmVarDecl &PD) {
62 if (FD.getNumParams() != O.getNumParams())
64 for (
unsigned I = 0, E = FD.getNumParams(); I < E; ++I) {
65 const ParmVarDecl *DPD = FD.getParamDecl(I);
66 const QualType OPT = O.getParamDecl(I)->getType();
68 if (!llvm::isa<RValueReferenceType>(OPT) ||
80 const ParmVarDecl &PD) {
86 DeclContext::lookup_result LookupResult =
87 FD.getParent()->lookup(FD.getNameInfo().getName());
88 if (LookupResult.isSingleResult()) {
91 for (
const Decl *Overload : LookupResult) {
94 if (
const auto *O = dyn_cast<FunctionDecl>(Overload))
102 const MatchFinder::MatchResult &Result) {
103 const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(
"func");
104 const auto *PD = Result.Nodes.getNodeAs<ParmVarDecl>(
"param");
105 const auto *DRef = Result.Nodes.getNodeAs<DeclRefExpr>(
"dref");
106 const SourceRange Range = DRef->getSourceRange();
107 if (Range.isInvalid())
113 diag(Range.getBegin(),
114 "returning a constant reference parameter may cause use-after-free "
115 "when the parameter is constructed from a temporary")