Skip to content

Commit a776bd1

Browse files
authored
[clang-tidy] support return c ? a : b; in bugprone-return-const-ref-from-parameter (#107657)
A `const &` parameter can also be returned via a conditional operator: `c ? a : b`. This change adds support for diagnosing returning these parameters with conditional operators.
1 parent 1897bf6 commit a776bd1

File tree

3 files changed

+34
-14
lines changed

3 files changed

+34
-14
lines changed

clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "ReturnConstRefFromParameterCheck.h"
10+
#include "clang/AST/Expr.h"
1011
#include "clang/ASTMatchers/ASTMatchFinder.h"
1112
#include "clang/ASTMatchers/ASTMatchers.h"
1213

@@ -15,19 +16,24 @@ using namespace clang::ast_matchers;
1516
namespace clang::tidy::bugprone {
1617

1718
void ReturnConstRefFromParameterCheck::registerMatchers(MatchFinder *Finder) {
19+
const auto DRef = ignoringParens(
20+
declRefExpr(
21+
to(parmVarDecl(hasType(hasCanonicalType(
22+
qualType(lValueReferenceType(pointee(
23+
qualType(isConstQualified()))))
24+
.bind("type"))))
25+
.bind("param")))
26+
.bind("dref"));
27+
const auto Func =
28+
functionDecl(hasReturnTypeLoc(loc(
29+
qualType(hasCanonicalType(equalsBoundNode("type"))))))
30+
.bind("func");
31+
32+
Finder->addMatcher(returnStmt(hasReturnValue(DRef), hasAncestor(Func)), this);
1833
Finder->addMatcher(
19-
returnStmt(
20-
hasReturnValue(declRefExpr(
21-
to(parmVarDecl(hasType(hasCanonicalType(
22-
qualType(lValueReferenceType(pointee(
23-
qualType(isConstQualified()))))
24-
.bind("type"))))
25-
.bind("param")))),
26-
hasAncestor(
27-
functionDecl(hasReturnTypeLoc(loc(qualType(
28-
hasCanonicalType(equalsBoundNode("type"))))))
29-
.bind("func")))
30-
.bind("ret"),
34+
returnStmt(hasReturnValue(ignoringParens(conditionalOperator(
35+
eachOf(hasTrueExpression(DRef), hasFalseExpression(DRef)),
36+
hasAncestor(Func))))),
3137
this);
3238
}
3339

@@ -85,8 +91,8 @@ void ReturnConstRefFromParameterCheck::check(
8591
const MatchFinder::MatchResult &Result) {
8692
const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("func");
8793
const auto *PD = Result.Nodes.getNodeAs<ParmVarDecl>("param");
88-
const auto *R = Result.Nodes.getNodeAs<ReturnStmt>("ret");
89-
const SourceRange Range = R->getRetValue()->getSourceRange();
94+
const auto *DRef = Result.Nodes.getNodeAs<DeclRefExpr>("dref");
95+
const SourceRange Range = DRef->getSourceRange();
9096
if (Range.isInvalid())
9197
return;
9298

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ Changes in existing checks
163163
<clang-tidy/checks/bugprone/posix-return>` check to support integer literals
164164
as LHS and posix call as RHS of comparison.
165165

166+
- Improved :doc:`bugprone-return-const-ref-from-parameter
167+
<clang-tidy/checks/bugprone/return-const-ref-from-parameter>` check to
168+
diagnose potential dangling references when returning a ``const &`` parameter
169+
by using the conditional operator ``cond ? var1 : var2``.
170+
166171
- Improved :doc:`bugprone-sizeof-expression
167172
<clang-tidy/checks/bugprone/sizeof-expression>` check to find suspicious
168173
usages of ``sizeof()``, ``alignof()``, and ``offsetof()`` when adding or

clang-tools-extra/test/clang-tidy/checkers/bugprone/return-const-ref-from-parameter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ int const &f3(TConstRef a) { return a; }
2727
int const &f4(TConst &a) { return a; }
2828
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter
2929

30+
int const &f5(TConst &a) { return true ? a : a; }
31+
// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: returning a constant reference parameter
32+
// CHECK-MESSAGES: :[[@LINE-2]]:46: warning: returning a constant reference parameter
33+
3034
template <typename T>
3135
const T& tf1(const T &a) { return a; }
3236
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter
@@ -47,6 +51,11 @@ template <typename T>
4751
const T& itf4(typename ConstRef<T>::type a) { return a; }
4852
// CHECK-MESSAGES: :[[@LINE-1]]:54: warning: returning a constant reference parameter
4953

54+
template <typename T>
55+
const T& itf5(const T &a) { return true ? a : a; }
56+
// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: returning a constant reference parameter
57+
// CHECK-MESSAGES: :[[@LINE-2]]:47: warning: returning a constant reference parameter
58+
5059
void instantiate(const int &param, const float &paramf, int &mut_param, float &mut_paramf) {
5160
itf1(0);
5261
itf1(param);

0 commit comments

Comments
 (0)