Skip to content

Commit d56f08b

Browse files
authored
[tidy] add new check bugprone-return-const-ref-from-parameter (#89497)
1 parent 4f4ebee commit d56f08b

File tree

8 files changed

+148
-0
lines changed

8 files changed

+148
-0
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "PosixReturnCheck.h"
5555
#include "RedundantBranchConditionCheck.h"
5656
#include "ReservedIdentifierCheck.h"
57+
#include "ReturnConstRefFromParameterCheck.h"
5758
#include "SharedPtrArrayMismatchCheck.h"
5859
#include "SignalHandlerCheck.h"
5960
#include "SignedCharMisuseCheck.h"
@@ -137,6 +138,8 @@ class BugproneModule : public ClangTidyModule {
137138
"bugprone-inaccurate-erase");
138139
CheckFactories.registerCheck<IncorrectEnableIfCheck>(
139140
"bugprone-incorrect-enable-if");
141+
CheckFactories.registerCheck<ReturnConstRefFromParameterCheck>(
142+
"bugprone-return-const-ref-from-parameter");
140143
CheckFactories.registerCheck<SwitchMissingDefaultCaseCheck>(
141144
"bugprone-switch-missing-default-case");
142145
CheckFactories.registerCheck<IncDecInConditionsCheck>(

clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule
2626
ImplicitWideningOfMultiplicationResultCheck.cpp
2727
InaccurateEraseCheck.cpp
2828
IncorrectEnableIfCheck.cpp
29+
ReturnConstRefFromParameterCheck.cpp
2930
SuspiciousStringviewDataUsageCheck.cpp
3031
SwitchMissingDefaultCaseCheck.cpp
3132
IncDecInConditionsCheck.cpp
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===--- ReturnConstRefFromParameterCheck.cpp - clang-tidy ----------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "ReturnConstRefFromParameterCheck.h"
10+
#include "../utils/Matchers.h"
11+
#include "clang/ASTMatchers/ASTMatchFinder.h"
12+
#include "clang/ASTMatchers/ASTMatchers.h"
13+
14+
using namespace clang::ast_matchers;
15+
16+
namespace clang::tidy::bugprone {
17+
18+
void ReturnConstRefFromParameterCheck::registerMatchers(MatchFinder *Finder) {
19+
Finder->addMatcher(
20+
returnStmt(hasReturnValue(declRefExpr(to(parmVarDecl(hasType(
21+
hasCanonicalType(matchers::isReferenceToConst())))))))
22+
.bind("ret"),
23+
this);
24+
}
25+
26+
void ReturnConstRefFromParameterCheck::check(
27+
const MatchFinder::MatchResult &Result) {
28+
const auto *R = Result.Nodes.getNodeAs<ReturnStmt>("ret");
29+
diag(R->getRetValue()->getBeginLoc(),
30+
"returning a constant reference parameter may cause a use-after-free "
31+
"when the parameter is constructed from a temporary");
32+
}
33+
34+
} // namespace clang::tidy::bugprone
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===--- ReturnConstRefFromParameterCheck.h - clang-tidy --------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RETURNCONSTREFFROMPARAMETERCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RETURNCONSTREFFROMPARAMETERCHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang::tidy::bugprone {
15+
16+
/// Detects return statements that return a constant reference parameter as
17+
/// constant reference. This may cause use-after-free errors if the caller uses
18+
/// xvalues as arguments.
19+
///
20+
/// For the user-facing documentation see:
21+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/return-const-ref-from-parameter.html
22+
class ReturnConstRefFromParameterCheck : public ClangTidyCheck {
23+
public:
24+
ReturnConstRefFromParameterCheck(StringRef Name, ClangTidyContext *Context)
25+
: ClangTidyCheck(Name, Context) {}
26+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
27+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
28+
std::optional<TraversalKind> getCheckTraversalKind() const override {
29+
// Use 'AsIs' to make sure the return type is exactly the same as the
30+
// parameter type.
31+
return TK_AsIs;
32+
}
33+
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
34+
return LangOpts.CPlusPlus;
35+
}
36+
};
37+
38+
} // namespace clang::tidy::bugprone
39+
40+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RETURNCONSTREFFROMPARAMETERCHECK_H

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ New checks
117117
Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP
118118
can be constructed outside itself and the derived class.
119119

120+
- New :doc:`bugprone-return-const-ref-from-parameter
121+
<clang-tidy/checks/bugprone/return-const-ref-from-parameter>` check.
122+
123+
Detects return statements that return a constant reference parameter as constant
124+
reference. This may cause use-after-free errors if the caller uses xvalues as
125+
arguments.
126+
120127
- New :doc:`bugprone-suspicious-stringview-data-usage
121128
<clang-tidy/checks/bugprone/suspicious-stringview-data-usage>` check.
122129

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.. title:: clang-tidy - bugprone-return-const-ref-from-parameter
2+
3+
bugprone-return-const-ref-from-parameter
4+
========================================
5+
6+
Detects return statements that return a constant reference parameter as constant
7+
reference. This may cause use-after-free errors if the caller uses xvalues as
8+
arguments.
9+
10+
In C++, constant reference parameters can accept xvalues which will be destructed
11+
after the call. When the function returns such a parameter also as constant reference,
12+
then the returned reference can be used after the object it refers to has been
13+
destroyed.
14+
15+
Example
16+
-------
17+
18+
.. code-block:: c++
19+
20+
struct S {
21+
int v;
22+
S(int);
23+
~S();
24+
};
25+
26+
const S &fn(const S &a) {
27+
return a;
28+
}
29+
30+
const S& s = fn(S{1});
31+
s.v; // use after free

clang-tools-extra/docs/clang-tidy/checks/list.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ Clang-Tidy Checks
120120
:doc:`bugprone-posix-return <bugprone/posix-return>`, "Yes"
121121
:doc:`bugprone-redundant-branch-condition <bugprone/redundant-branch-condition>`, "Yes"
122122
:doc:`bugprone-reserved-identifier <bugprone/reserved-identifier>`, "Yes"
123+
:doc:`bugprone-return-const-ref-from-parameter <bugprone/return-const-ref-from-parameter>`
123124
:doc:`bugprone-shared-ptr-array-mismatch <bugprone/shared-ptr-array-mismatch>`, "Yes"
124125
:doc:`bugprone-signal-handler <bugprone/signal-handler>`,
125126
:doc:`bugprone-signed-char-misuse <bugprone/signed-char-misuse>`,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %check_clang_tidy %s bugprone-return-const-ref-from-parameter %t
2+
3+
using T = int;
4+
using TConst = int const;
5+
using TConstRef = int const&;
6+
7+
namespace invalid {
8+
9+
int const &f1(int const &a) { return a; }
10+
// CHECK-MESSAGES: :[[@LINE-1]]:38: warning: returning a constant reference parameter
11+
12+
int const &f2(T const &a) { return a; }
13+
// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: returning a constant reference parameter
14+
15+
int const &f3(TConstRef a) { return a; }
16+
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: returning a constant reference parameter
17+
18+
int const &f4(TConst &a) { return a; }
19+
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter
20+
21+
} // namespace invalid
22+
23+
namespace valid {
24+
25+
int const &f1(int &a) { return a; }
26+
27+
int const &f2(int &&a) { return a; }
28+
29+
int f1(int const &a) { return a; }
30+
31+
} // namespace valid

0 commit comments

Comments
 (0)